关于Linq to sql的一个更新问题

本文探讨了在LINQ to SQL中实现分层应用程序时遇到的对象更新难题。当对象实例从一个DataContext传递到另一个DataContext环境中时,如何正确地进行更新操作。通过设置IsVersion属性并使用Attach方法成功解决了跨DataContext更新的问题。
最新也开始研究linq to sql,但随着深入,发现无论是国外还是国内文档还是很少,估计随后一段时间文档会多起来。
现在有一个更新问题。
先从Datacontext中得到一个实体丢出去,然后对这个实体进行更新,测试了很长时间没有发现好的方式。
         public  Page SavePage(Page page)
        
{
            DataContext dxt 
= new DataContext("server=.;database=xxx");
            dxt.GetTable
<Page>().Attach(page);
            
            dxt.SubmitChanges();           
            
return page;
        
        }
其中page从丢出去后已经变化了,但SubmitChanges()后没有更新数据库。
试了很久都不行,最终采用这样的方式可以。
         public   void  SavePage < T > (T obj, Action < T >  update) where T: class
        
{
            DataContext dxt 
= new DataContext("server=.;database=giga");
            dxt.GetTable
<T>().Attach(obj);
            
//dxt.GetTable<T>().Attach(obj);
            update(obj);
            dxt.SubmitChanges();
        }

// 调用
            dataAccess.Update < Page > (page,  delegate (Page p)
            
{
                p.PageTitle 
= "aaa";
            }
);
// dataAccess是上面函数的实例

上面代码的更新可以成功的。
难道对于一个对象的更新会这么复杂?大家有没有更简单的方法?

posted on 2007-07-31 10:04 Axel 阅读(1376) 评论(20)  编辑 收藏 所属分类: linq

Feedback

#1楼  2007-07-31 10:29 木野狐

http://www.codeproject.com/vista/LINQ2.asp   回复  引用  查看    

#2楼 [楼主] 2007-07-31 10:57 Axel

@木野狐
谢谢回复!以前就看了这个文章的,文中并没有给答案。
我的问题主要是这个实例是从不同的层递交过来的,这个时候原先Datacontext的已经没有了。
现在网上所有的文档都是在一个datacontext环境中写的例子的,但对于分层的应用中必须要用到Attach这个方法把另外一个datacontext产生的实例Attach到当前的datacontext环境中来。
  回复  引用  查看    

#3楼  2007-07-31 11:29 Boler Guo

Hi Axel,

Did you try dxt.GetTable<Page>().Attach(page, true);   回复  引用  查看    

#4楼 [楼主] 2007-07-31 11:35 Axel

@Boler Guo
试过。会丢出An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy.错误。
也就是这个实例丢出去后原先的状态没有了。所以我才用到第二个方法。   回复  引用  查看    

#5楼  2007-07-31 12:10 宋国安

我想问下,你是怎么丢出去的?是delete了?还是怎么了?
如果该实体在数据库中,不存在了,该用Add方法吧!   回复  引用  查看    

#6楼 [楼主] 2007-07-31 12:18 Axel

@宋国安
也就是这个实例并不是从同一个datacontext环境中出来的。
这个是分层中常用的。
我先从服务器端Get出来一个实例,递交给客户端,这时服务端的datacontext已经不存在了。然后从客户端返回,这时候必须要重建一个datacontext,那么这个时候就必须把这个实例Attach到这个datacontext中。
并没有delete。   回复  引用  查看    

#7楼 [楼主] 2007-07-31 12:26 Axel

核心问题是,更新不是在同一个Datacontext实例中。
网上所有的例子都是,对象实例从一个datacontext实例中得到,然后对象实例发生变化,再从同一个datacontext实例中去更新,这个太简单了。只要SubmitChanges就能成功。
现在问题的焦点是,对象实例从一个datacontext实例中得到,但后来这个datacontext不存在了,对象实例到别的层里去转了一圈,然后要更新,这时必须要重建一个Datacontext实例,然后这个对象实例附加进来。   回复  引用  查看    

#8楼  2007-07-31 12:30 Martin Yao [未注册用户]

1. Add IsVersion=true to the 'Page' table primary key column mapping attribute. I assume it is PageID. So it should be.
[Column(Storage="_PageID"...., IsVersion=true)]
2. Use dxt.GetTable<Page>().Attach(page, true);

Could you try it again?
  回复  引用  查看    

#9楼 [楼主] 2007-07-31 12:36 Axel

@Martin Yao
谢谢,哈哈。果然是这样,先前我没有理解IsVersion含义,把它加到别的字段中去了。在关键字加上这个就好了。
另外我试一下IsVersion加到时间戳字段看看行不行。
  回复  引用  查看    

#10楼  2007-07-31 12:38 宋国安

我倒,c#组的人都出动了。...

Let me introduce IsVersion.

This file indicates that this file represents a TimeStamp field in Sql Server that is automatically updated each time when the row is changed.

This fields can be used to enable more efficient optimistic concurrency conflict detection.

我感觉问题不在这里,你好像是webservice?需要序列化。
If you’re using SqlMetal to generate you DataContext then you can choose not to pass in the /pluralize flag.
if you are using OR designer
You can turn off pluralization from Options dialog within VS. It’s under “Database Tools->O/R Designer”.   回复  引用  查看    

#11楼 [楼主] 2007-07-31 12:43 Axel

@宋国安
谢谢,问题就是An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy.错误
加上IsVersion就好了。


  回复  引用  查看    

#12楼  2007-07-31 14:12 jjx

你还没有碰到关系呢 ,linq to sql 在分布式环境中处理关系n头大,莫名的错误提示一大堆   回复  引用  查看    

#13楼 [楼主] 2007-07-31 14:19 Axel

@jjx
是,应用深入后就变得复杂了,所谓问题不少还是缺少相关文档的原因。有什么问题大家讨论。
我自己通过codesmith写的生成工具,没有用vs2008的生成工具,主要是我的关系还不在同一层里。另外自己定制codesmith模块要可以更灵活。
我现在在设计的时候尽可能使对象间的关系简单化,不然就算有加载延迟也是很大的负担。
现在我在mapping映射时有些犹豫,到底是采用特性还是XML,现在这两个都支持,但我感觉效率会不一样,什么时候测试一下。   回复  引用  查看    

#14楼  2007-08-01 15:05 R2 [未注册用户]

是不是需要在自动生成的代码里面加IsVersion的属性啊,可这样,如果改动dbml文档,不就把修改过的代码覆盖掉了,似乎不是正解,期待高手解答。   回复  引用  查看    

#15楼  2007-08-01 15:14 R2 [未注册用户]

哦,IsVersion在OR Designer里面是可以设置,把Time Stamp设置为true就可以了。   回复  引用  查看    

#16楼 [楼主] 2007-08-01 15:14 Axel

我加上IsVersion就更成功了。如果是分层的应用,就不能用dbml产生代码。我是自己通过codesmith维护。   回复  引用  查看    

#17楼  2007-08-02 15:50 江南白衣

如果是分层的应用,就不能用dbml产生代码
==========================
此话怎讲?   回复  引用  查看    

#18楼  2007-08-02 22:23 yee [未注册用户]

晕死,把isversion加在关键字上...
isversion是用来做并发控制的.
不过,解决方法是错误的.

唉...无语.   回复  引用  查看    

#19楼  2007-08-02 22:25 yee [未注册用户]

对不起,打错字了.
应该是这样解决的.加一个timestamp字段,标识这个字段为version(isversion)
,问题就解决了.   回复  引用  查看    

#20楼  2007-09-15 19:27 cokkiy [未注册用户]

简单的问题为什么要搞复杂呢?Attach 是你在数据库里面已经有了记录,只是在外面修改了,你需要更新回去,采用Attach.如没有,请用Add就OK。
DataContext db=new DataContetx();

Page p=db.Pages.Single(p=>p.ID==ModifiedOrNewPage.ID);
if(p!=null)
{
db.Pages.Attach(ModifiedOrNewPage,p);
}

else
db.Pages.Add(ModifiedOrNewPage);
db.SubmitChanges();

这个IsVersion一点关系都没有。如果有Version字段,更新是效率高一点而已,不同去检查每个字段了。
  回复  引用  查看    

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值