Entity Framework,查询 dbset,包括上下文更改而不调用保存更改

Entity Framework, query dbset including context changes without to call save changes

我想知道如何获得我将用 EF6 解释的这种行为。

想象一下,我有我的 DbContext,我正在对它执行操作,在相关的 DbSet 上查询、删除和添加记录。

想象一下,我有来自 DB 的 Person DbSet 最初有 3 条记录

我这样做:

using (var pc = new PersonContext())
{
   pc.Persons.Add(new Person("Mario","Rossi"));//add 1 record
   var pcount=pc.Persons.Count();//still 3 recors and not 4 as expected
   //Complex opertions...
   pc.SaveChanges();
}

我想将 DbSets 与 DbContext 一起使用更新(删除、添加、修改)记录,而不必每次都调用 SaveChanges 方法。

想象一下,在最终 SaveChanges 之前,我可以执行大量复杂的操作。

不仅仅是交易,因为我知道我可以获得这样的东西:

using (var pc = new PersonContext())
{
    pc.Database.BeginTransaction();
    pc.Persons.Add(new Person("Mario","Rossi"));//add 1 record
    pc.SaveChanges();
    var pcount=pc.Persons.Count();//4 as expected
    //Complex opertions
    pc.Database.CurrentTransaction.Commit();
}

考虑到跟踪更改,是否有任何方法无需编写大量代码即可获得此信息?

1.First 创建通用存储库接口:

  public interface IRepository<T> : IDisposable
        where T : class
    {
     IQueryable<T> GetAll();
     T FirstOrDefault(Expression<Func<T, bool>> predicate);
     T Create(T item);
     int Update(T item);
     int Delete(T item);
    }

2.Then 通用存储库:

  public class Repository<T> : IRepository<T> where T : class
{
        private DbContext _context;
        private DbSet<T> DbSet
        {
            get { return _context.Set<T>(); }
        }

        public Repository(DbContext context)
        {
            this._context = bookContext;
        }
         public IQueryable<T> GetAll()
        {
            return DbSet.AsNoTracking().AsQueryable();
        }
        public T FirstOrDefault(Expression<Func<T, bool>> predicate)
        {
            return DbSet.FirstOrDefault(predicate);
        }

        public T Create(T item)
        {
            if (item == null)
                throw new ArgumentNullException(nameof(item));
          using (var scope = new TransactionScope())
          {
            DbSet.Add(item);
            _context.SaveChanges();
            scope.Complete();
            return item;
          }
        }

        public int Update(T item)
        {
            if (item == null)
                throw new ArgumentNullException(nameof(item));
          using (var scope = new TransactionScope())
          {
            var entry = _context.Entry(item);
            DbSet.Attach(item);
            entry.State = EntityState.Modified;
            var result= _context.SaveChanges();
            scope.Complete();
            return result;
          }
        }
         public int Delete(T item)
        {
            if (item == null)
                throw new ArgumentNullException(nameof(item));
           using (var scope = new TransactionScope())
           {
             DbSet.Remove(item);
            var result= _context.SaveChanges();
            scope.Complete();
            return result;
           }
        }

        private bool disposed = false;
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                  _context.Dispose();
                }
            }
            this.disposed = true;
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
}

3.Create 人员资料库:

public interface IPersonRepository : IRepository<Person>
{
}

public class PersonRepository : Repository<Person>, IPersonRepository
{
    public PersonRepository(DbContext context) : base(context) { }
}

4.Use: 示例:

 PersonContext context= new PersonContext();
 IPersonRepository _personRepository= new PersonRepository(context);
_personRepository.Create(new Person("Mario","Rossi"));

或 使用 IoC container 进行依赖注入。(我强烈推荐这个)。 并使用(ASP.NET MVC 的示例)

public class PersonController:Controller
{
    IPersonRepository _personRepository;
    public PersonController(IPersonRepository personRepository){
        _personRepository=personRepository;
    }
    public ActionResult Create()
    {
      var person= _personRepository.Create(new Person("Mario","Rossi"));
        return View();
    }
}

阅读有关 Repository and Unit of Work Patterns 的 Microsoft 文档。

由于 DbSet 将始终为您提供来自数据库的数据,因此框架中没有自动执行我想要的方法。

有一个名为 'Local' (https://msdn.microsoft.com/en-us/library/system.data.entity.dbset.local(v=vs.113).aspx#P:System.Data.Entity.DbSet.Local) 的特定 DbSet 属性,代表该集合中所有已添加、未更改和已修改实体的本地视图。

最后,我们应该从 DbSet 查询开始编写一些代码,并在结果列表上应用跟踪到 DbSet.Local 集合中的操作。