我正在使用Entity Framework& LINQ检索数据。我遇到以下问题:
var customer= db.customers.where(c=>c.id==1);
customer.name=santhosh;
customer.city=hyd;
在我打电话之前,数据库中的字段正在发生变化:
db.SaveChanges();
我该如何避免这种情况?
答案 0 :(得分:2)
在我调用
之前,数据库中的字段正在发生变化
如果您的意思是更改应用程序外部更改,例如SQL Management Studio中的更改。实体框架无法检测到这些更改,因此您可能会获得由Entity Framework缓存的过时对象。要防止接收缓存对象并从数据库中获取最新值,请使用AsNoTracking。
尝试使用AsNoTracking():
var customer= db.customers.AsNoTracking().where(c=>c.id==1);
customer.name=santhosh;
customer.city=hyd;
db.SaveChanges();
或者,如果您的问题是检测并发更新(unfortunate terminology,它不仅适用于UPDATE)到同一行,请使用rowversion(aka timestamp)字段类型;然后在您的.NET代码上添加属性的Timestamp
属性。示例:http://www.ienablemuch.com/2011/07/entity-framework-concurrency-checking.html
public class Song
{
[Key]
public int SongId { get; set; }
public string SongName { get; set; }
public string AlbumName { get; set; }
[Timestamp]
public virtual byte[] Version { get; set; }
}
更新(发表评论后):
如果您真的无意将对象更改持久保存到数据库中。尝试分离对象。
试试这个:
var customer= db.customers.where(c=>c.id==1);
db.Entry(customer).State = System.Data.EntityState.Detached; // add this
customer.name=santhosh;
customer.city=hyd;
db.SaveChanges();
这不会将您对名称和城市的更改保存到数据库。
如果你想要更健壮的东西(如果对象尚未附加,上述内容将失败),请创建一个帮助器:
private static void Evict(DbContext ctx, Type t,
string primaryKeyName, object id)
{
var cachedEnt =
ctx.ChangeTracker.Entries().Where(x =>
ObjectContext.GetObjectType(x.Entity.GetType()) == t)
.SingleOrDefault(x =>
{
Type entType = x.Entity.GetType();
object value = entType.InvokeMember(primaryKeyName,
System.Reflection.BindingFlags.GetProperty,
null, x.Entity, new object[] { });
return value.Equals(id);
});
if (cachedEnt != null)
ctx.Entry(cachedEnt.Entity).State = EntityState.Detached;
}
使用:Evict(yourDbContextHere, typeof(Product), "ProductId", 1);
http://www.ienablemuch.com/2011/08/entity-frameworks-nhibernate.html
答案 1 :(得分:2)
检查是否将db对象传递给其他方法,并在那里调用SaveChanges()?
或者检查是否有异常的catch块,并且您可能在catch块中使用SaveChanges()来记录错误消息?
(这些是常见的编程错误)
答案 2 :(得分:2)
正如其他人所说的那样,我相信你也在另一个地方使用你的上下文,而其他地方正在调用savechanges并更新所有内容。尝试使用@Evan建议的使用陈述来确保你有一个新的背景。
AsNoTracking不会确保您获得未在数据库中缓存的实体,其目的是不将对象放在上下文中。如果您使用AsNoTracking,然后更改查询中返回的实体,则需要在调用savechanges之前将它们作为修改后附加到上下文,否则它们将不会更新。
var customer= db.customers.AsNoTracking().Single(c=>c.id==1);
customer.name=santhosh;
customer.city=hyd;
ctx.customers.Attach(customer);
ctx.ObjectStateManager.ChangeObjectState(customer, System.Data.EntityState.Modified);
我会对其他帖子发表评论,但还没有足够的代表。
答案 3 :(得分:1)
你能再提供一些周围的代码吗?如果没有看到你如何构建你的背景,可能会有点困难。
这就是我通常处理更新的方式(我希望它可以提供一些见解):
using (var ctx = new myModel.myEntities())
{
int pollID = 1;
var poll = (from p in ctx.Polls
where p.PollID == pollID
select p).FirstOrDefault();
poll.Question = txtPoll.Text.Trim();
ctx.SaveChanges();
}
答案 4 :(得分:0)
我不得不为SQL Compact更改一点。
var customer= db.customers.AsNoTracking().Single(c=>c.id==1);
db.customers.Attach(customer);
customer.name=santhosh;
customer.city=hyd;
db.ObjectStateManager.ChangeObjectState(customer, System.Data.EntityState.Modified);
db.SaveChanges();
db.Dispose();
这工作得更好。