实体框架,查询包含上下文更改的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,而不调用保存更改的主要内容,如果未能解决你的问题,请参考以下文章
DbContext.set() 无法为实体创建 DbSet,因为此类型未包含在上下文的模型中
无法为“ApplicationUser”创建 DbSet,因为此类型未包含在上下文模型中