【问题标题】:querying a collection against a byte property in mongodb with c# driver使用 c# 驱动程序在 mongodb 中针对字节属性查询集合
【发布时间】:2016-03-30 11:27:34
【问题描述】:

我对 mongodb 相当陌生,我正在尝试使用 byte 属性查询集合,但我得到了一个无效的强制转换异常。总而言之,

public class MongoDbAddressCollection    
{
     private IMongoCollection<Addresses> collection = database.GetCollection<Addresses>("AddressCollection");
     public IEnumerable<Addresses> Where(System.Linq.Expressions.Expression<Func<Addresses, bool>> filter = null)
     {
         var items = collection.AsQueryable().Where(filter);
         if (items == null)
             return null;
         return items.ToList();
     }
}

public class Test
{
    public void DoSomthingWithAddresses()
    {
         MongoDbAddressCollection addressCollection=new MongoDbAddressCollection();
         //exception occurs in MongoDbAddressCollection.Where method when executing the ToList().
         List<Addresses> homeAddresses=addressCollection.Where(x=>x.AddressType==(byte)EnumAddressType.HomeAddress);
         foreach(var address in homeAddresses)
         {
            //do stuff
         }
    }
}

地址实体如下类

public class Address
{
    public Guid UserId { get; set; }
    public string Street { get; set; }
    public byte AddressType { get; set; }
    .....
}

public enum EnumAddressType
{
    HomeAddress=1,
    WorkAddress=2
}

实际上问题似乎是 mongodb 和 .net 之间的类型不匹配,我可以看到 WorkAddress 实体的 AddressType 是 10,这是 2 的二进制表示。但是,除了更改所有字节属性之外,我想不出解决方案在我们将所有实体插入到集合之前将它们转换为 int(我们在不同的实体中有很多字节属性)...或者可以通过查询中的解决方法来解决这个问题(linq where 条件)?

提前致谢。

【问题讨论】:

    标签: c# mongodb linq mongodb-query mongodb-.net-driver


    【解决方案1】:

    byte类型的序列化确实有问题。我认为最快的解决方案是将AddressType 属性的类型从byte 更改为EnumAddressType

    public class Address
    {
        public Guid UserId { get; set; }
        public string Street { get; set; }
        public EnumAddressType AddressType { get; set; }
    }
    

    并在不强制转换的情况下编写您的过滤器:

    var filter = Builders<Address>.Filter
        .Where(x => x.AddressType == EnumAddressType.HomeAddress);
    

    您可以使用此方法测试您的过滤器:

    public static BsonDocument RenderToBsonDocument<T>(FilterDefinition<T> filter)
    {
        var serializerRegistry = BsonSerializer.SerializerRegistry;
        var documentSerializer = serializerRegistry.GetSerializer<T>();
        return filter.Render(documentSerializer, serializerRegistry);
    }
    

    结果

    var json = RenderToBsonDocument(filter).ToJson();
    // Result: { "AddressType" : 1 }
    

    作为一种替代方法,您可以编写自定义字节序列化程序并使用以下方法进行注册:

    BsonClassMap.RegisterClassMap<Address>(cm =>
    {
        cm.AutoMap();
        cm.GetMemberMap(c => c.AddressType).SetSerializer(MyCustomByteSerializer.Instance);
    });
    

    你可以在这里看到sample serializer code

    【讨论】:

    • 谢谢门南的回答。将属性类型更改为枚举并不是一个真正的选项,因为该属性对应于数据库中的 tinyint 列并且实体是自动生成的...我尝试了自定义序列化程序,现在 mongodb 中的数据很好,但我仍然得到一个执行 Where(filter).ToList() 方法时出现异常。
    猜你喜欢
    • 2012-09-02
    • 2012-05-15
    • 2012-03-04
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 2017-07-09
    • 1970-01-01
    相关资源
    最近更新 更多