当前位置:编程学习 > C#/ASP.NET >>

Linq 整体更新一行数据的问题


abc _entity = db.abc.SingleOrDefault(e => e.id == 123);//id是主键,自增列
_entity = entity;
db.SubmitChanges();


为什么整体修改一行记录总是不能成功呢。如果换成每个属性重新赋值的话,就没问题。请大侠帮忙解决一下,很急。 --------------------编程问答-------------------- 对了,补充一下:之前我用的vs2008都是这么用的,没出现上述问题,现在改用vs2010了,才有这个问题。 --------------------编程问答-------------------- 确保entity
各字段与_entity一致,只是修改某些 --------------------编程问答-------------------- entity哪儿来的?为什么不直接修改? --------------------编程问答-------------------- 源代码少贴了点


DataClasses1DataContext db = new DataClasses1DataContext();

//页面处理新的对象
        string name = txtName.Text.Trim();
       abc entity = db.abc.SingleOrDefault(e => e.id == Convert.ToInt32(Request.QueryString["id"]));
       entity.cname = name;
       Update(entity);       


       //数据访问层处理Update方法
         public void Update(abc entity)
        {
            abc _entity = db.abc.SingleOrDefault(e => e.id == entity.id);
            _entity = entity;
            db.SubmitChanges();
        }


修改时,我不指定修改了哪些字段,而是直接修改整个实体(entity),然后提交数据库修改。因为如果字段很多的话,不想每个字段都重新赋值。(我在vs2008的项目中都是这么做的,而且没问题,vs2010就不行了,不知道是否跟vs版本有关系呀。) --------------------编程问答-------------------- 这个可以肯定的说,跟VS版本没有关系 --------------------编程问答-------------------- 你这两行的代码 赋值的意思 要弄清楚,基础,内存分布问题,跟VS 哪有关系。
//在托管堆一个变量_entity 指向db.abc.SingleOrDefault(e => e.id == entity.id);
abc _entity = db.abc.SingleOrDefault(e => e.id == entity.id);
//变量_entity 指向entity,不再指向原来那个了。  
//db.abc.SingleOrDefault(e => e.id == entity.id); 和_entity 并没有发生关系
 _entity = entity;
// 没有改变,你保存啥?
db.SubmitChanges();
--------------------编程问答--------------------
引用 6 楼 claymore1114 的回复:
你这两行的代码 赋值的意思 要弄清楚,基础,内存分布问题,跟VS 哪有关系。
//在托管堆一个变量_entity 指向db.abc.SingleOrDefault(e => e.id == entity.id);
abc _entity = db.abc.SingleOrDefault(e => e.id == entity.id);
//变量_entity 指向entity,不再指向原来那……


_entity是从数据库中查出的
entity是内存中已经改过的新的实体
_entity=entity是在内存中更新从数据库查出的记录,之前好多项目一直这么写的,没有问题。只是现在发现这样不管用了。 --------------------编程问答--------------------
引用 7 楼 richie8398 的回复:
引用 6 楼 claymore1114 的回复:
你这两行的代码 赋值的意思 要弄清楚,基础,内存分布问题,跟VS 哪有关系。
//在托管堆一个变量_entity 指向db.abc.SingleOrDefault(e => e.id == entity.id);
abc _entity = db.abc.SingleOrDefault(e => e.id == entity.id);
//……

你以前的也肯定不行,行的话,那肯定跟这个不一样。  哈哈 坐等  专家来解释。 --------------------编程问答--------------------
引用 8 楼 claymore1114 的回复:
引用 7 楼 richie8398 的回复:
引用 6 楼 claymore1114 的回复:
你这两行的代码 赋值的意思 要弄清楚,基础,内存分布问题,跟VS 哪有关系。
//在托管堆一个变量_entity 指向db.abc.SingleOrDefault(e => e.id == entity.id);
abc _entity = db.abc.SingleOrDefault(e =>……


这个我敢肯定一样,因为好多项目都是这样写的。 --------------------编程问答-------------------- 我的理解
堆栈 _entity  变量 一开始指向 
 托管堆(假设内存A) db.abc.SingleOrDefault(e => e.id == entity.id);
经过赋值
堆栈 _entity  变量 指向 托管堆(假设内存B) entity
A和B 是一样的?
db.SubmitChanges();执行保存的还是A, A并没有发生变化。
--------------------编程问答--------------------
引用 10 楼 claymore1114 的回复:
我的理解
堆栈 _entity 变量 一开始指向 
 托管堆(假设内存A) db.abc.SingleOrDefault(e => e.id == entity.id);
经过赋值
堆栈 _entity 变量 指向 托管堆(假设内存B) entity
A和B 是一样的?
db.SubmitChanges();执行保存的还是A, A并没有发生变化。


_entity和entity是不一样的,entity是经过修改后的(比如:里面的name值变化了)。所以_entity=entity,这样的结果是_entity也变成了经过修改后的实体。我觉得你还是没有看明白我上面贴的代码。 --------------------编程问答-------------------- 哎! 怎么说不通呢
_entity之前的假设为A
_entity赋值为entity(假设B)之后,_entity里面的值当然是entity(你修改后的),因为它指向entity,操作它的属性后,仍然是在操作B区。
_entity没有指向A了,也不能操作A,_entity你再怎么折腾,跟A没关系了。

而db.SubmitChanges(); 是操作A的,不是操作B的。
--------------------编程问答-------------------- 之前好多项目一直这么写的,没有问题。只是现在发现这样不管用了。
=============

以前的项目悲剧了,要不就是以前你们用了另外一个类似的框架,但不是你现在用的这个。 --------------------编程问答-------------------- 晕,之前一直用的linq的框架,更新都是这么写的。 --------------------编程问答-------------------- 要不你以前的项目重载了=运算符,通过反射全部自动赋值了一遍 --------------------编程问答-------------------- 确实没有用到反射,因为我也参与了框架的设计。所以,我肯定跟现在的写法一样。晕了,谁能帮我解决一下 --------------------编程问答--------------------    abc entity = db.abc.SingleOrDefault(e => e.id == Convert.ToInt32(Request.QueryString["id"]));
       entity.cname = name;

SingleOrDefault 返回的可能是空.
那么下一条
entity.cname = name;
就是错的.因为entity没有new. --------------------编程问答--------------------
引用楼主 richie8398 的回复:
C# code

abc _entity = db.abc.SingleOrDefault(e => e.id == 123);//id是主键,自增列
_entity = entity;
db.SubmitChanges();



为什么整体修改一行记录总是不能成功呢。如果换成每个属性重新赋值的话,就没问题。请大侠帮忙解决一下,很急。


如果你肯但凡看一下EF的官方实例,你会发现没有任何一段代码是写成这样的。
DataContext是比较傻的:一旦你用它读出一个entity,然后如果你又将其Close,那么这个entity就被称作detached,也就是说此实体脱离了DataContext的监控,使得DataContext无法跟踪此实体的变化。所以,要么你就保持DataContext一直打开(不推荐),要么就在Update的时候再将实体attach回DataContext,然后再SaveChanges;我从网上找了一个小例子给你,不要纠结于那个T,那只是个范类而已。


public void UpdateObject(T obj)
{
    using (var context = new MyDataContext())
    {
        context.CreateObjectSet<T>().Attach(obj);
        context.ObjectStateManager.ChangeObjectState(obj, EntityState.Modified);
        context.SaveChanges();
    }
}

--------------------编程问答-------------------- 再补充一点:
虽然你有_entity = entity,但很可能你的entity已经脱离了“生出”这个entity的DataContext的“监控”,而另一个DataContext对此entity是完全陌生的,它不知道什么属性改变了,什么没改变,这时候如果你去Update(_entity),即Update(entity),是无效的。 --------------------编程问答-------------------- public void ConvertPro<TSource>(TSource model1, TSource model2)
    {
        PropertyInfo[] properties = model1.GetType().GetProperties();
        Type t = model2.GetType();
        foreach (var item in properties)
        {
            t.InvokeMember(item.Name, BindingFlags.SetProperty, null, model2, new object[] { item.GetValue(model1, null) });
        }
    }


--------------------编程问答--------------------
补充:.NET技术 ,  LINQ
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,