代码之家  ›  专栏  ›  技术社区  ›  Abhijeet

将EF Core InMemory数据库序列化为JSON

  •  0
  • Abhijeet  · 技术社区  · 6 年前

    尝试了此操作,但无法序列化。

            var deltaJson = "";
            try
            {
                var modifiedEntries = _ctx.ChangeTracker
                    .Entries()
                    .Select(x => x.Entity)
                    .ToList();
                deltaJson = JsonConvert.SerializeObject(modifiedEntries, Formatting.Indented);
            }
    

    我的下一个希望是使用内存数据库,如果可能的话 序列化DbContext的整个对象图。

    可行吗?你的专家建议和任何指向这个方向的建议都会很有帮助。

    我自己的版本:

    public class DeltaTracking
    {
        public static List<T> Build<T>(ICollection<T> db, ICollection<T> req) where T : IR
        {
            return Build(db, req, new DT<T>());
        }
    
        public static List<T> Build<T>(ICollection<T> db, ICollection<T> req, IEqualityComparer<T> comp) where T : IStateTracking
        {
            db = db ?? new List<T>();
            req = req ?? new List<T>();
    
            List<T> added = req.Except(db, comp).ToList();
            foreach (T a in added)
            {
                a.State = TrackingState.Added.ToString();
            }
    
            List<T> removed = db.Except(req, comp).ToList();
            foreach (T r in removed)
            {
                r.State = TrackingState.Deleted.ToString();
            }
    
            List<T> unchanged = db.Intersect(req, comp).ToList();
            foreach (T u in unchanged)
            {
                u.State = TrackingState.Unchanged.ToString();
            }
            List<T> resp = added.Union(removed, comp).Union(unchanged, comp).ToList();
            return resp;
        }
    }
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Steve Py    6 年前

    您可以从变更跟踪器序列化实体,但是考虑到这听起来像是您想要序列化和卸载大量的变更,您可能需要将变更打包到较小的页面中,跨线路传输它们,在另一侧跟踪和组合变更集,并确保它们按照顺序重新组合,因为变更集将跨越相关实体。

    const int pageSize = 1000;
    var count = context.ChangeTracker.Entries()
        .Count(x => x.State == EntityState.Modified || x.State == EntityState.Added || x.State == EntityState.Deleted);
    
    var pages = (int) Math.Ceiling((double) count / PageSize);
    int loopCounter = 0;
    while (loopCounter < pages)
    {
       var changes = context.ChangeTracker.Entries()
          .Where(x => x.State == EntityState.Modified || x.State == EntityState.Added || x.State == EntityState.Deleted)
          .Select(x => new { Type = x.Entity.GetType(), State = x.State.ToString(), Original = x.OriginalValues.ToObject(), Updated = x.CurrentValues.ToObject() })
          .Skip(loopCounter * pageSize)
          .Take(pageSize);
    
       var data = new
       {
          PageNumber = loopCounter,
          Changes = changes,
       };
    
       string changeData = JsonConvert.SerializeObject(data, Formatting.Indented);
       // Fire across to destination to be processed. Be sure to send the total # of pages because the server cannot start processing these unless they are in order.
    

    .Changes 将包含类型、状态(要执行的操作、更新、添加、删除)以及适用的原始和更新的实体值。

    如果这只是处理批更新,则排除添加/删除项并让它们通过。

    另一个真正的测试是在进行更改的时间和后台服务运行更改的时间之间的并发性。您应该考虑检查版本控制是否有任何更新。这可能不是一个完整的解决方案,但希望它能提供一些想法或引发一些讨论。

        2
  •  -1
  •   John White    6 年前

    总是可以侧着身子做一些消息传递(MSMQ,RabbitMQ)。您的进程一次向队列发送一个“事务”,侦听器一次发送一个,完全异步。可以从接收端生成多个进程以获得更好的吞吐量。