根据实体框架文档,实体框架仅在使用.Find()
查询数据时缓存数据。
在以下示例中,我使用.First()
时缓存了查询数据:
static void Main(string[] args)
{
var trxScope = new TransactionScope();
var context = new SekhavatDBEntities();
//the value of Balance is Zero
var account =
context.Accounts.First(acc => acc.Id == new Guid("79B7AAC6-AD2D-4824-907E-16ADB4C41EE1"));
account.Balance = 50;
context.SaveChanges();
trxScope.Dispose();
var trxScope2 = new TransactionScope();
var account2 =
context.Accounts.First(acc => acc.Id == new Guid("79B7AAC6-AD2D-4824-907E-16ADB4C41EE1"));
//Balance of account2 Is 50 Now!
trxScope2.Dispose();
}
为什么account2的余额为50?根据我的考虑,它应该是0。
提前致谢
答案 0 :(得分:3)
以下是documentation的相关引用:
请注意,DbSet和IDbSet始终会针对数据库创建查询 并且将始终涉及到数据库的往返,即使 返回的实体已存在于上下文
中...
从数据库返回结果时,不存在的对象 在上下文中附加到上下文。 如果某个对象已在 上下文,返回现有对象(当前和原始对象) 条目中对象属性的值不会被覆盖 数据库值)。
使用交易与否是无关紧要的。相关的是:
EF不会在事务回滚时将值更改回原始值(我认为它甚至不可能这样做,但无论如何)。如果您使用TransactionScope
或ctx.Database.BeginTransaction
在您进行第二次查询时,您的帐户ID为79B7AAC6-AD2D-4824-907E-16ADB4C41EE1已被上下文跟踪。根据上述文档 - 将对数据库进行查询,但此查询的结果将被丢弃,并且不会覆盖当前跟踪的实体的值。相反,实体将按原样返回(余额等于50)。
要防止这种情况:
为单独的操作使用单独的上下文,并尽可能避免重复使用上下文。
使用AsNoTracking
。这将阻止上述行为,并且将始终返回实体,因为它现在在数据库中。
使用Reload
:
context.Entry(account).Reload();
这将查询此实体的数据库,并使用当前数据库值覆盖所有值。
答案 1 :(得分:1)
您的TransactionScope
必须在您的上下文中并开始交易
如果您按照自己的方式声明了
,那么您的上下文中没有打开的事务使用 Celso Livero等信息表示=> MSDN Page
using (var context = new SekhavatDBEntities())
{
using (var dbContextTransaction = context.Database.BeginTransaction())
{
var account = context.Accounts.First(acc => acc.Id == new Guid("79B7AAC6-AD2D-4824-907E-16ADB4C41EE1"));
account.Balance = 50;
context.SaveChanges();
dbContextTransaction.Rollback();
}
}
使用其他context
检查数据
using (var context = new SekhavatDBEntities())
{
var account2 = context.Accounts.First(acc => acc.Id == new Guid("79B7AAC6-AD2D-4824-907E-16ADB4C41EE1"));
}
First()
或Find()
不是您的交易问题。
并且像 Erk 一样说,看到在上下文中已经存在具有相同键的实体
数据在您的context
中缓存,而不是因为您使用的是First()
或Find()
答案 2 :(得分:0)
使用AsNoTracking()
//the value of Balance is Zero
var account =
context.Accounts.AsNoTracking().First(acc => acc.Id == new Guid("79B7AAC6-AD2D-4824-907E-16ADB4C41EE1"));