2011-10-08 18 views
16

Tengo una clase User y necesito trabajar con ellos en servicios web.MongoDB C#: Serialización ID mejor patrón

Entonces problema es que si trato de serializar Id que es el tipo de BsonObjectId, veo que tienen una propiedad vacía, que tiene una propiedad vacía, y así sucesivamente ...

tengo escribir esta solución en orden, es una buena solución?

public partial class i_User 
{ 
    [BsonId(IdGenerator = typeof(BsonObjectIdGenerator))] 
    [NonSerialized] 
    public BsonObjectId _id; 

    public String Id 
    { 
     get 
     { 
      return this._id.ToString(); 
     } 
    } 
} 

De esta manera, puedo mantener _Id como BsonObjectId pero me envíe un representación de cadena a través de Internet en la propiedad Id.

Otra solución es trabajar con StringObjectIdGenerator

public partial class i_User 
{ 
    [BsonId(IdGenerator = typeof(StringObjectIdGenerator))] 
    public String id; 
} 

Pero es ver que MongoDB almacenará un string en base de datos en lugar de ObjectId.

¿Cuál es el mejor enfoque para trabajar en una serialización ambiental como servicios web y/o un cliente-servidor (Flash + C#)?

Respuesta

90

Si le entiendo correctamente, quiere acceder a la propiedad Id como una cadena, pero tenga el Id guardado como ObjectId en MongoDB. Esto se puede lograr utilizando BsonRepresentation con BsonId.

[BsonId] 
[BsonRepresentation(BsonType.ObjectId)] 
public string Id { get; set; } 

Los detalles se pueden encontrar here.

+3

¡Gracias! Yo votaría por ti dos veces si pudiera;) – Doobi

+1

me acabas de salvar el día – emreturan

+1

Pasé 2 horas peleando contra una respuesta webapi que no serializaría un ObjectId sin procesar. Esto me ahorró probablemente 2 horas más –

6

Si desea hacerlo con una asignación de clase - esta es la manera de hacerlo:

BsonClassMap.RegisterClassMap<i_User>(cm => 
{ 
    cm.AutoMap(); 
    cm.SetIdMember(cm.GetMemberMap(x => x.Id) 
    .SetIdGenerator(StringObjectIdGenerator.Instance)); 
}); 
+0

Esta es una manera muy agradable donde POCO permanece limpio, que es mi principal preocupación. Pero en realidad almacenará Id como cadena en Mongo. Lo ideal sería tener representación de ObjectId en la base de datos y representación de cadenas en POCO. ¿Es eso posible? –

+0

No es que yo sepa, pero supongo que puede modificar el controlador C#. El objetivo del uso de ObjectId es que solo toma 12 bytes y tiene una marca de tiempo incorporada. ¿Por qué no usar ObjectId en las entidades de su dominio? – Lybecker

+1

Gracias por una respuesta rápida. Por lo general, quiero que mi capa de dominio sea independiente de la técnica de capa de almacenamiento. Pero creo que todo es una compensación. –

1

También hay un enfoque más genérico utilizando convenciones. Este enfoque le permite configurar reglas para todos los modelos en un solo lugar.

Primero. Agregue una convención para generador de ID

public class IdGeneratorConvention : ConventionBase, IPostProcessingConvention 
{ 
    public void PostProcess(BsonClassMap classMap) 
    { 
     var idMemberMap = classMap.IdMemberMap; 
     if (idMemberMap == null || idMemberMap.IdGenerator != null) 
     { 
      return; 
     } 

     idMemberMap.SetIdGenerator(StringObjectIdGenerator.Instance); 
    } 
} 

Segundo. Registra nuestra convención El método Register se debe llamar antes de la primera consulta.

var conventionPack = new ConventionPack { new IdGeneratorConvention() }; 
ConventionRegistry.Register("Pack", conventionPack, x => true);