实体框架,查询包含上下文更改的dbset,而不调用保存更改

时间:2018-02-27 00:16:44

标签: entity-framework transactions unit-of-work

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

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

想象一下,我有来自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();
}

考虑到跟踪变化,有没有办法获得这个而不必编写大量代码?

2 个答案:

答案 0 :(得分:0)

1.首先创建一个Generic Repository接口:

  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.然后是通用存储库:

  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.创建人员存储库:

public interface IPersonRepository : IRepository<Person>
{
}

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

4.使用:  例如:

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

OR 使用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文档

答案 1 :(得分:0)

由于DbSet总是会从数据库中为您提供数据,因此没有一种自动方式从框架中执行我想要的操作。

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

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