查询mongodb中有子对象的时候,结果报错 返回

SqlSugar 沟通中
88 809

在子对象的属性上也加了[SugarColumn(IsJson = true)]

但是最后查询时,报错为:

System.InvalidCastException:“Unable to cast object of type 'System.Collections.Generic.Dictionary`2[System.String,System.Object]' to type 'System.IConvertible'.”


数据为:

image.png实体定义为:

image.png

热忱回答88

  • 报错代码怎么写的 ,是插入还是查询

    0 回复
  • @fate sta:查询啊,自己报错的,截图在上面啊

    image.png

    0 回复
  • image.png

    这个tojson删掉

    不是ORM的方法吧

    0 回复
  • 直接ToList()看一下是不是OK

    0 回复
  • @fate sta:一样的,不是tojson造成的。

    而且,你插入的时候,数据库里面的值也不对

    image.png


    这是什么鬼?:Dimage.png

    0 回复
  • 按下面的模版写个可以重现的DEMO

    0 回复
  • using SqlSugar;
    using SqlSugar.MongoDb;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace MongoDbTest
    {
        public class QueryJsonArray
        {
            internal static void Init()
            {
                var db = DbHelper.GetNewDb();
                db.CodeFirst.InitTables<Student>();
                db.DbMaintenance.TruncateTable<Student>();
                db.Insertable(new Student() { Age = 1, Name = "tom", SchoolId = "a", Book = new List<Book>() { new Book() { CreateTime = DateTime.Now, Price = 21 } } }).ExecuteCommand();
                var data1=db.Queryable<Student>().ToList();
         
            }
    
            [SqlSugar.SugarTable("UnitStudentdfsds3zzz1")]
            public class Student : MongoDbBase
            {
                public string Name { get; set; }
    
                public string SchoolId { get; set; }
    
                public int Age { get; set; }
    
                public DateTime CreateDateTime { get; set; }
    
                [SqlSugar.SugarColumn(IsJson = true)]
                public List<Book> Book { get; set; }
            }
    
            public class Book
            {
                public decimal Price { get; set; }
                public DateTime CreateTime { get; set; }
            }
        }
    
    }


    0 回复
  • 在我的基础上改一版本能重现的

    0 回复
  • @fate sta:你插入数据的时候估计将子对象转换成数据流了,然后存进去都是byte数组。

    我元数据是springboot写进去的,用其他的工具也是正常读取,使用了sqlsugar才不对的。你还是看看子对象在写入的时候是不是有什么问题吧。期待你的修复。

    0 回复
  • @兔子罗杰:就是说这个东西不是ORM写入的吗?

    0 回复
  • @fate sta:你应该在IsJson的属性上,将子对象变成json数组,然后字符串的形式拼接上父对象,这样应该就对了,感谢参考我的建议。

    0 回复
  • 这个需要提供远程字符串,我不清楚你的表里面存的什么样的格式。

    0 回复
  • @fate sta:也是ORM写入的呀,Springboot的ORM写入,用.net的mongodb驱动也能读出来,用其他软件,比如flink for java,都读出正确啊。

    0 回复
  • 不清楚你说的是什么意思。

    0 回复
  • @fate sta:很简单啊,mongodb里面就是json格式啊,我那个子对象最后就是一个json数组啊

    0 回复
  • @fate sta:那你写个可以重现的DEMO给我。

    0 回复
  • 我这边需要能重现的。因为我重现不了我也不知道怎么改

    0 回复
  • @fate sta:重现什么,跟你上面提供的模版一样的代码啊,但是你插入的时候就是字节流啊

    0 回复
  • @fate sta:就是你再看看,子对象写入的时候是怎么弄的

    0 回复
  • db.Ado.ExecuteCommand(@"insertMany UnitSchool123131  [{ ""Name"" : ""XX大学"" }]");

    用SQL写个可以重现的

    0 回复
  • @fate sta:这个是写主数据,没有问题的吧

    0 回复
  • @兔子罗杰:你写个可以重现的。。我只是个示例。。

    0 回复
  • 你用Mongodb命令写个可以重现的

    0 回复
  • @fate sta:还有,如果你写子对象有问题,只能把子对象变成json字符串了,或者JsonObject什么的

    0 回复
  • @兔子罗杰:需要DEMO。。这样沟通太浪费时间了

    0 回复
  •    public static string ConnectionString = "mongodb://root:123456@117.72.212.3:27017/testDB?authSource=admin";

      这个是公网的mongodb数据库,你可以在这个上面搞一个表 写一个DEMO

    0 回复
  • @fate sta:好,一会我试试

    0 回复
  • @fate sta:我插入了一条我这里的数据,你可以用你们的代码操作一下看看

    0 回复
  • @兔子罗杰:实体类发出来

    0 回复
  • 报错的代码最好提供完整

    0 回复
  • @fate sta

    [SugarTable("a")]

    public class VehicleTracksEO : MongoDbBase

    {

        //外键需要设置ObjectId类型不然存储会的是string

        [SugarColumn(ColumnDataType = nameof(ObjectId))]

        public string orderId { get; set; } = string.Empty;


        [SugarColumn(ColumnDataType = nameof(ObjectId))]

        public string carId { get; set; } = string.Empty;


        [SugarColumn(IsJson = true)]

        public List<Point> latlngPoints { get; set; } = [];

    }


    public class Point

    {

        public string? vehicleNo { get; set; } = string.Empty;


        public double lat { get; set; }


        public double lng { get; set; }


        public long timestamp { get; set; }

    }

    你们直接用你们的代码来操作啊

    0 回复
  • image.png


    一条记录都没有。 是a表吗

    0 回复
  • 是a表啊,你看你都读取不出来

    0 回复
  • @fate sta是a表啊,你看你都读取不出来

    0 回复
  • @兔子罗杰:库对吗

    0 回复
  • @fate sta:我在你们a表手动插入了一条数据啊,现在应该是两条

    0 回复
  • @fate sta:就是你给我的库链接啊

    0 回复
  • 写个空DEMO能重现发我 删掉OBJ和BIN打包上传。这样沟通太浪费时间了

    0 回复
  • @fate sta:你 aggregate a怎么可以嘛?!

    0 回复
  •             var client = new MongoClient("mongodb://root:123456@117.72.212.3:27017/testDB?authSource=admin");
                var database = client.GetDatabase("testDB");
                var collections = database.GetCollection<BsonDocument>("a");
                var list = collections.AsQueryable<BsonDocument>().ToList();

    原生都查不到

    0 回复
  • 你至少保证用mongodb原生驱动能查到

    0 回复
  • @fate sta:不好意思,数据库错了,是SqlSugarDb,呵呵

    0 回复
  • @fate sta:我刚才验证过了,你们的那个IsJson有问题,对象没转成json字符串

    我把属性改正字符串,去掉IsJson标签,写入和读取就对了

    0 回复
  • @兔子罗杰

    image.png


    我拿掉也是NULL

    0 回复
  • 你最好写个DEMO 吧。这样浪费时间

    0 回复
  • @fate sta:我又在testDB里面的OrderInfo表里面建立了同样的数据,你们不换数据库的话,就用OrderInfo表吧

    0 回复
  • 提供完整DEMO 。

    0 回复
  • 并且能重现

    0 回复
  • 删掉OBJ和BIN打包上传

    0 回复
  • @fate sta:所以说,你的是空的,说明你对字段序列化的时候没弄好,尤其是IsJson的时候,就应该把这个字段变成字符串,然后子类json序列化进去,拼上父类,一次写入mongodb

    0 回复
  • 提供DEMO。能重现的 。

    0 回复
  • @fate staimage.png

    image.png

    这样就对了。

    但是,你们的IsJson就根本没用了

    0 回复
  • 浪费很多时间了 ,按你说的无论去掉Isjon都是空的。

    0 回复
  • 不提供可以重现的DMEO不在回复了。

    0 回复
  • @fate sta:就三个文件


    // https://www.donet5.com/home/Doc/3?typeId=2651

    using Dm;

    using HBDbToolBySqlSugar;

    using MongoDB.Bson;


    Console.WriteLine("请输入要生成实体类的表名(空格分隔,回车生成)");


    var tables = Console.ReadLine();


    var instance = DbTool.Instance("mongodb://", SqlSugar.DbType.MongoDb);

    //instance.GenerateEntities(["VehicleTracks"]);

    //instance.GetDb().Queryable<VehicleTracksEO>().ToList().ForEach(x =>

    //{

    //    Console.WriteLine($"OrderId: {x.OrderId}, CarId: {x.CarId}, Points Count: {x.LatlngPoints}");

    //});


    var result = instance.GetDb().Queryable<VehicleTracksEO>().Where(it => it.Id == "6864dc62d35094e98ec9dc73").ToList().ToJson();

    Console.WriteLine(result);

    Console.ReadLine();


    //var data = new List<Point>

    //{

    //    new() {

    //        vehicleNo = "车牌号1",

    //        lat = 39.9042,

    //        lng = 116.4074,

    //        timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()

    //    },

    //    new() {

    //        vehicleNo = "车牌号2",

    //        lat = 34.0522,

    //        lng = 118.2437,

    //        timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()

    //    }

    //};

    //instance.GetDb().Insertable(new VehicleTracksEO

    //{

    //    orderId = ObjectId.GenerateNewId().ToString(),

    //    carId = ObjectId.GenerateNewId().ToString(),

    //    latlngPoints = data.ToJson()

    //}).ExecuteCommand();



    ========================================================================

    using MongoDB.Bson;

    using SqlSugar;

    using SqlSugar.MongoDb;


    namespace HBDbToolBySqlSugar

    {

        [SugarTable("VehicleTracks")]

        public class VehicleTracksEO : MongoDbBase

        {

            //外键需要设置ObjectId类型不然存储会的是string

            [SugarColumn(ColumnDataType = nameof(ObjectId))]

            public string orderId { get; set; } = string.Empty;


            [SugarColumn(ColumnDataType = nameof(ObjectId))]

            public string carId { get; set; } = string.Empty;


            //[SugarColumn(IsJson = true)]

            public string latlngPoints { get; set; } = string.Empty;

        }


        public class Point

        {

            public string? vehicleNo { get; set; } = string.Empty;


            public double lat { get; set; }


            public double lng { get; set; }


            public long timestamp { get; set; }

        }

    }

    ============================================================

    using SqlSugar;

    using System.Data;

    using System.Reflection;


    namespace HBDbToolBySqlSugar

    {

        public class DbTool

        {

            private readonly SqlSugarClient _db;


            private static readonly DbTool? _instance;


            public static DbTool Instance(string connectionString, SqlSugar.DbType dbType) => _instance ?? new DbTool(connectionString, dbType);


            private DbTool(string connectionString, SqlSugar.DbType dbType)

            {

                _db = new SqlSugarClient(new ConnectionConfig

                {

                    ConnectionString = connectionString,

                    DbType = dbType,

                    IsAutoCloseConnection = true

                },

                it =>

                {

                    it.Aop.OnLogExecuting = (sql, para) =>

                    {

                        Console.WriteLine(UtilMethods.GetNativeSql(sql, para));

                    };

                });

            }


            public SqlSugarClient GetDb()

            {

                return _db;

            }


            

        }

    }


    0 回复
  • 提供完整可以跑的。

    0 回复
  • 删掉OBJ和BIN打包上传

    0 回复
  • @fate sta:那你们还是再看看子集记录是在mongodb里面怎么保存的吧,可能你们在开发的时候还没考虑到这种情况。

    我也是随便测试一下,毕竟直接用.net的BSON直接可以操作数据。等你们后续发现问题再测试升级吧 :)

    0 回复
  • 我这边已经重现了,你用的A表名是我已存在的表名

    导致2条记录一条是我以前插入的结构

    一条是新插入的结构

    因为结构不一样导致读取失败。

    0 回复
  • SqlSugar.MongoDbCore 5.1.4.203


    更新这个版本查询的修复了 ,保证每条记录的结构一致。

    0 回复
  • @fate sta:monogodb里面的数据字段不可能每条保持一致。

    上一条记录的结构和下一条记录的结构可以不一致的,mongodb是取合集,比如,第一条记录是 name, addr, 第二条记录只有mobile,那么它作为一条记录显示就变成三个字段了,即:name,addr,mobile

    0 回复
  • @兔子罗杰: ORM要读取有哪些列。以第一条为基准。

    0 回复
  • 保证第一条是标准的。

    0 回复
  • 保证第一条是标准的。

    0 回复
  • @fate sta

    我用mongodb.drive自带的insert和查询,对带有子集的记录插入和查询都是没有问题的,而且都是可以读取和写入我提供的数据结构的。

    而我发觉用sqlsugar插入和查询还是有问题,用你说的最新版本。

    大多是出现在MongoDbInsertBuilder里面 :)

    0 回复
  • @兔子罗杰:你不提供DEMO我这边进度会很慢。因为我只慢慢摸索。你说的出错是哪儿出错我也不清楚

    0 回复
  • 我这边测试用例是OK的。空表写入

    0 回复
  • -
    0 回复
  • using MongoDB.Bson;
    using SqlSugar.MongoDb;
    using SqlSugar;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace MongoDbTest 
    {
        internal class Unitdfasfysfs
        {
            public static void Init() 
            {
                var db = DbHelper.GetNewDb();
                db.Insertable(new VehicleTracksEO()
                {
                    carId= ObjectId.GenerateNewId() + "",
                    orderId =ObjectId.GenerateNewId()+"",
                    latlngPoints=new List<Point>() { 
                     new Point(){ lat=1, lng=1, timestamp=11, vehicleNo="aa" }
                    }
    
                }).ExecuteCommand();
                var list=db.Queryable<VehicleTracksEO>().ToList();
            }
        }
        [SugarTable("unitadsfasfdsys")]
    
        public class VehicleTracksEO : MongoDbBase
    
        {
    
            //外键需要设置ObjectId类型不然存储会的是string
    
            [SugarColumn(ColumnDataType = nameof(ObjectId))]
    
            public string orderId { get; set; } = string.Empty;
    
    
    
            [SugarColumn(ColumnDataType = nameof(ObjectId))]
    
            public string carId { get; set; } = string.Empty;
    
    
    
            [SugarColumn(IsJson = true)]
    
            public List<Point> latlngPoints { get; set; } =new List<Point>() { };
    
        }
    
    
    
        public class Point
    
        {
    
            public string? vehicleNo { get; set; } = string.Empty;
    
    
    
            public double lat { get; set; }
    
    
    
            public double lng { get; set; }
    
    
    
            public long timestamp { get; set; }
    
        }
    }

    完整测试用例 跟本重现不了你说的。

    0 回复
  • @fate sta:我的demo都在上面贴了啊

    然后我找了有问题的地方,MongoDbInsertBuilder

    image.png


    image.png

    你们有空再查一下吧 :)

    0 回复
  • @兔子罗杰:你的源码不是最新的

    image.png

    0 回复
  • 查询的我已经改过了,多加了一个if

    0 回复
  • 插入目前没有发现任何问题

    image.png

    0 回复
  • SqlSugar.MongoDbCore 5.1.4.204


     这次应该都好了 更新到204

    0 回复
  • image.png

    0 回复
  • @fate sta

    整体测试下来,基本只能用个基础功能,还是不能用嵌套数据(数据操作的结果根本不对),跟mongodb.driver提供的自身的orm不好比,可能你们的实现思路是有问题的。

    建议这个SqlSugar.MongodbCore可以取消了,Mongodb.Drver本身就可以ORM。当然,你们要让mongodb通过sqlsugar和其他数据库中的数据join,可以重新设计一下SqlSugar.MongodbCore的功能。

    题外话,Mongodb是放json数据的,每条json数据的结构是可以不同的,mongodb显示是所有记录字段的合并集。

    0 回复
  • @fate sta

    image.png

    这是我用Mongodb.Driver自己提供的ORM来读取数据的,两条记录你可以用两个不同的实体来读取,实际存储数据在你们的数据库SqlSugarDb.a表中,如下

    image.png

    0 回复
  • image.png 第一条是错误记录删掉。

    0 回复
  • 实体结构是固定的。用ORM的话你不能用mongodb的思维设计表结构。

    0 回复
  • 针对这种不同结构我在想一下如何去处理

     [ {id:`1} {name:"a"} ]

    比如返回这种合并后的结构。

    [{id:1,name:null},{id:0,name;"a"}]

    0 回复
  • 原生的功能也支持

    image.png

    0 回复
  • @fate sta:实体结构是固定的,但是你可以将不同实体往一个表里面写哦,你读取的时候可以根据指定不同的实体类来取数据哦。

    mongodb是用来存文档的,不同文档的格式是可以在同一个表里面的,这个也是mongodb最大的好处啊。


    internal class BaseService<TEntity> where TEntity : class, new()

    {

        protected readonly IMongoCollection<TEntity> _collection;


        public BaseService()

        {

            var client = new MongoClient("mongodb://root:123456@117.72.212.3:27017/SqlSugarDb?authSource=admin");

            var database = client.GetDatabase("SqlSugarDb");

            _collection = database.GetCollection<TEntity>("a");

        }


        public async Task<List<TEntity>> GetAllAsync() =>

        await _collection.Find(_ => true).ToListAsync();

    }

    你看,我用原生的,比你们的这个SqlSugar.MongodbCore方便多了,最多自己再写个分页,ok

    0 回复
  • @fate sta:mongodb,最大的好处是能够检索json里的不同数据,因为最后都变成动态的字段。

    如果换了其他的数据库,你的json只能当一个字符串字段来存取。

    SqlSugar.MongoDBCore这个项目最多封装一下原生的ORM得了,他反正也不是做复杂sql查询的。

    0 回复
  • @fate sta:上面贴图里面的两条数据不是错误数据,正是我原生ORM写入的数据和你写入的数据一同展示的。我就是跟你说明,不同结构的数据是可以在一个表里面的。

    0 回复
  •  这个已经在处理了。支持不同结构的读取

    0 回复
  • SqlSugar.MongoDbCore 5.1.4.205

    过五分钟升级到 205

    0 回复
  •  image.png

    新版本测试, 我这边是可以了

    SqlSugar.MongoDbCore 5.1.4.205


    0 回复
  • @fate sta:测了一下,凑合可以读取。

    为什么说是凑合呢,因为,你们还是在数据转换上会报错。应该是那个外键的objectid,一定是字符串的问题吧。但是我在其他系统里面设置的是long类型哦,到了你这里转换就还是会报错。

    如果想做到完美匹配其他语言写入的mongodb数据,你们这个版本还得动脑筋升级啊  :D

    0 回复