当前位置: 首页 > 编程语言 > C#

没有数据上下文如何保存Linq对象?分享

时间:2023-04-10 23:19:35 C#

没有datacontext如何保存Linq对象?我有一个Linq对象,我想对其进行更改并像这样保存它:publicvoidDoSomething(MyClassobj){obj.MyProperty="Changed!";MyDataContextdc=newMyDataContext();dc.GetTable().Attach(dc,true);//抛出异常dc.SubmitChanges();异常是:System.InvalidOperationException:如果一个实体声明了一个版本成员或没有更新检查策略,那么它只能被附加为没有原始状态的修改。看起来我有几个选择:在我需要以这种方式使用的每个Linq类和表(100+)上放置一个版本成员。找到最初创建对象的数据上下文,并使用它来提交更改。在每个类中实现OnLoaded并保存此对象的副本,我可以将其作为基线对象传递给Attach()。进行并发检查;在附加之前加载数据库版本并将其用作基线对象(不是!!!)选项(2)似乎是最优雅的方法,特别是如果我能找到一种方法来在创建对象时存储数据对引用上下文的方法。但是——怎么办?还有其他想法吗?编辑我尝试遵循JasonPunyon的建议并在表上创建一个并发字段作为测试用例。我在dbml文件的字段上设置了所有正确的属性(TimeStamp=true等),现在我有一个并发字段......和一个不同的错误:System.NotSupportedException:已尝试附加或添加实体这不是新的,可能是从另一个DataContext加载的。这是不支持的。那么,如果不是现有实体,我应该附加什么?如果我想要一条新记录,我会执行InsertOnSubmit()!那么应该如何使用Attach()呢?编辑——全面披露好吧,我明白是时候全面披露为什么没有一个标准模式对我有用了。我一直在尝试通过对“消费者”开发人员隐藏DataContext来变得聪明并使我的界面更清晰。我通过创建一个基类publicclassLinqedTablewhereT:LinqedTable{...}...我的每个表都有其生成的“另一半”版本声明如下:publicpartialclassMyClass:LinqedTable{}LinqedTable有很多实用方法,特别是:publicstaticTGet(longID){//加载具有给定ID的记录的代码//所以你可以这样写://MyClassobj=MyClass.Get(myID);//而不是://MyClassobj=myDataContext.GetTable().Where(o=>o.ID==myID).SingleOrDefault();}publicstaticTableGetTable(){//所以你可以这样写查询://varq=MyClass.GetTable();//而不是://varq=myDataContext.GetTable();}当然,如您所想,这意味着LinqedTable必须能够以某种方式访问??DataContext。直到最近,我通过在静态上下文中缓存DataContext来实现这一点。是的,“直到最近”,因为“最近”是因为我发现你真的不应该坚持使用DataContext来处理超过一个工作单元,否则各种各样的孩子都会从木工开始。学到的知识。所以现在我知道我不能长时间保留这个DataContext......这就是为什么我开始尝试按需创建一个DataContext,只缓存在当前的LinqedTable实例上。这导致了新创建的DataContext与我的对象无关的问题,因为它“知道”它不忠实于创建它的DataContext。有没有办法在创建或加载时将DataContext信息推送到LinqedTable?这真是装腔作势。我绝对不想在我放入LinqedTable基类中的所有这些便利功能上做出妥协,我需要能够在必要时删除DataContext并在需要时继续使用它。还有其他想法吗?“当一个实体如果声明了一个版本成员,则只能在没有原始状态的情况下进行修改”,当附加一个带有时间戳成员的权限时,那么它(只应该)发生错误(读取:已被序列化和反序列化)。如果您正在使用未使用WCF的本地测试应用程序或其他导致实体被序列化和反序列化的东西进行测试,它们仍将保留通过entitysets/entityrefs(associations/nav.properties)引用对原始数据上下文的访问.如果是这种情况,您可以通过在调用数据上下文的.Attach方法之前在本地进行序列化和反序列化来解决这个问题。例如:internalstaticTCloneEntity(ToriginalEntity){TypeentityType=typeof(T);DataContractSerializerser=newDataContractSerializer(entityType);使用(MemoryStreamms=newMemoryStream()){ser.WriteObject(ms,originalEntity);多发性硬化症。位置=0;返回(T)ser.ReadObject(ms);或者您可以通过将所有entitysets/entityrefs设置为null来分离它,但这更容易出错,所以虽然有点昂贵,但我只想在本地进行模拟n层行为时使用上面的DataContractSerializer方法。.(相关主题:http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/eeeee9ae-fafb-4627-aa2e-e30570f637ba)使用LINQtoSQL进行更新很有趣。如果数据上下文消失(在大多数情况下应该消失),那么您将需要获取新的数据上下文,并运行查询以检索要更新的对象。在LINQtoSQL中,必须检索对象才能删除它是绝对规则,并且应该检索对象才能更新它。有变通办法,但它们很丑陋,而且通常有更多方法可以帮助您。所以,重新获取记录并完成它。一旦获得重新获取的对象,它就会用包含更改的现有对象的内容进行更新。然后对新数据上下文执行SubmitChanges()。就这样!通过将记录中的每个值与原始(重新获取的)记录进行比较,LINQtoSQL将生成一个相当苛刻的乐观并发版本。如果在获取数据时更改了任何值,LINQtoSQL将抛出并发异常。(所以你不需要为版本控制或时间戳更改所有表。)如果你对生成的更新语句有任何疑问,你将不得不跳出SQLProfiler并观察更新被发送到数据库.在您对生成的SQL有信心之前,这是一个好主意。关于事务的最后一个注意事项——如果没有环境事务,数据上下文将为每个SubmitChanges()调用生成一个事务。如果您正在更新多个项目并希望将它们作为一个事务运行,请确保对所有项目使用相同的数据上下文并等待调用SubmitChanges()直到所有对象内容都已更新。如果这个事务方法不可行,那么寻找一个TransactionScope对象。这将是你的朋友。我认为2不是最佳选择。听起来您正在创建一个DataContext并在程序的整个生命周期内保持它的活动状态,这是一个坏主意。DataContext是轻量级对象,可以在需要时旋转。尝试保留引用也可以紧密耦合程序的各个区域,而不是将它们分开。一次运行一百个ALTERTABLE语句,重新生成上下文并保持模式简单和分离是优雅的答案......找到最初创建对象的数据上下文,并使用它来提交更改你的数据上下文去哪儿了?为什么这么难找?你一次只用一个吗?那么,如果不是现有实体,我应该附加什么?如果我想要一条新记录,我会执行InsertOnSubmit()!那么应该如何使用Attach()呢?您应该附加一个代表现有记录的实例......但不被另一个数据上下文加载-您不能在同一个实例上有两个上下文跟踪记录状态。如果您生成一个新实例(即克隆),那么您就可以开始了。您可能想查看这篇文章及其关于并发模式的更新和删除部分。您可以重新连接到新的DataContext。在正常情况下唯一阻止您执行此操作的是发生在EntitySet和EntityRef类中的属性更改事件注册。要允许实体在上下文之间传输,实体必须首先通过删除这些事件注册从DataContext分离,然后使用DataContext.Attach()方法重新附加到新的上下文。这是一个很好的例子。首次检索数据时,在执行检索的上下文中关闭对象跟踪。这将防止在原始上下文中跟踪对象状态。然后,在保存值时,附加到新上下文,刷新以从数据库设置对象的原始值,然后提交更改。当我测试它时,以下对我有用。以上是C#学习教程:没有数据上下文如何保存Linq对象?如果分享的内容对你有用,需要了解更多C#学习教程,希望大家多多关注——MyClassobj=null;使用(DataContextcontext=newDataContext()){context.ObjectTrackingEnabled=false;obj=(frompincontext.MyClasseswherep.ID==someIdselectp).FirstOrDefault();}obj.Name+="测试";使用(DataContextcontext2=new()){context2.MyClasses.Attach(obj);context2.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues,obj);context2.SubmitChanges();}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: