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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实体框架,查询包含上下文更改的dbset,而不调用保存更改相关的知识,希望对你有一定的参考价值。

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

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

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

我这样做:

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更新(删除,添加,修改)记录,而无需每次调用​​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.首先创建一个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"));

或者使用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集合中的操作。

以上是关于实体框架,查询包含上下文更改的dbset,而不调用保存更改的主要内容,如果未能解决你的问题,请参考以下文章

我可以在选择时让我的实体框架DbSet调用我的表值函数吗?

DbContext.set() 无法为实体创建 DbSet,因为此类型未包含在上下文的模型中

无法为“ApplicationUser”创建 DbSet,因为此类型未包含在上下文模型中

IDENTITY_INSERT ON不被实体框架DBSet.Add方法所尊重

为啥实体框架核心加载实体的关系而不添加包含

在实体框架中,DbSet.Local 保持不同步