代码之家  ›  专栏  ›  技术社区  ›  void.pointer

向从DbSet.ToList获得的列表添加新项

  •  0
  • void.pointer  · 技术社区  · 3 年前

    EFCore的文档(使用.net5)显示,要添加项,需要使用底层 DbSet 直接。然而,我目前的设计如下:

    我有一个用于获取基础数据集的接口:

    public interface IServiceCache
    {
        IEnumerable<T> Load<T>();
        void Save<T>(IEnumerable<T> objList);
    }
    

    DbContext

    internal class DatabaseServiceCache : IServiceCache
    {
        private readonly IDbContextFactory<DatabaseContext> _contextFactory;
    
        public DatabaseServiceCache(IDbContextFactory<DatabaseContext> contextFactory)
        {
            _contextFactory = contextFactory;
        }
    
        public IEnumerable<T> Load<T>()
        {
            var context = _contextFactory.CreateDbContext();
            return context.Set<T>();
        }
    
        public void Save<T>(IEnumerable<T> objList)
        {
            var context = _contextFactory.CreateDbContext();
            // TODO: What to do with `objList`?
            // Something like this? `context.Set<T>() = objList` (this won't work obviously)
            context.SaveChanges(); // in case elements were modified directly
        }
    }
    

    还有我的 DatabaseContext 班级:

    public class DatabaseContext : DbContext
    {
        public DbSet<IdMapping> CacheIdMapping { get; set; }
    }
    

    所以我会用 IServiceCache 像这样:

    var cache = new DatabaseServiceCache(contextFactory); // assume DI-injected, and that we give it the `contextFactory`
    var theList = cache.Load<IdMapping>().ToList();
    theList[0].SomeProperty = 100; // modify existing objects
    theList.Add(new IdMapping()); // add new objects
    cache.Save(theList); // save modified and added items
    

    1. 我在数据库中查询表示缓存项列表的完整记录集
    2. 我修改该列表和/或向同一列表添加新项目
    3. 我保存了列表,其中应该包括修改和添加的项目。

    然而,到目前为止,我不认为这将工作,因为唯一的变化跟踪后执行 ToList() 是对现有项目的修改。假设这个说法是正确的,我的问题是:

    请注意,我非常高兴被告知我的设计需要改变。最初,我将磁盘上的JSON文件作为我的主要用例来设计它。所以我可能还没有“跳出框框思考”,可能是想把一个方形的销钉塞进一个圆孔里。

    我是EFCore的新手,所以可能也缺少一些基本的概念。

    0 回复  |  直到 3 年前
        1
  •  1
  •   benuto    3 年前

    调用Save(objList)方法时,dbContext是全新的,对列表的更改一无所知。 一种解决方案是遍历所有列表对象,从db读取和更新实体,然后保存更改()。 显然,这是一个非常糟糕的主意。

    新添加的项的主键为0。请使用Add或AddRange方法将它们添加到dbset。

    我假设JSON文件会刷新覆盖旧文件的所有内容。 在数据库的情况下,您使用的是一个记录,而遍历所有记录是“不必要的”。

    上下文工厂很好,但是如果您所做的只是寻找对象、操作对象并保存到dbase,那么可以将dbcontext作为私有字段。只在阅读之前启动它们,但在保存之前保持打开状态。

    另一种方法是在数据库上下文上实现IServiceCache。 ef肯定会跟踪对现有记录的修改,您所要做的就是将新的objectc添加到dbset,然后调用saveChanges。

    class DatabaseContext: IServiceCache {...}
    
    
    
    var cache= contextFactory.Create(..)
    ..
    theList = cache.Load();
    ..Add();
    cache.Save(theList) {
    
    DBSet<T>().AddRange(theList.Where(x=>x.Id == 0));
    }