你如何保存LINQ的对象,如果你没有它的数据上下文? [英] How do you save a Linq object if you don't have its data context?

查看:380
本文介绍了你如何保存LINQ的对象,如果你没有它的数据上下文?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个LINQ的对象,我要进行更改并保存它,像这样:

I have a Linq object, and I want to make changes to it and save it, like so:

public void DoSomething(MyClass obj) {
  obj.MyProperty = "Changed!";
  MyDataContext dc = new MyDataContext();
  dc.GetTable<MyClass>().Attach(dc, true); // throws exception
  dc.SubmitChanges();
}



唯一的例外是:

The exception is:

System.InvalidOperationException: 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.



它看起来像我有几个选择:

It looks like I have a few choices:


  1. 将一个版本的成员对我的LINQ类及放大器中的每一个;表(100+),我需要以这种方式使用。

  2. 找到最初创建该对象的数据上下文,并用它来提交修改。

  3. 在每一类中实现OnLoaded并保存此对象的副本,我可以传递给连接()作为基准对象

  4. 要与并发检查地狱。刚刚安装之前装入数据库版本,并用其作为基准对象(不是!)

  1. put a version member on every one of my Linq classes & tables (100+) that I need to use in this way.
  2. find the data context that originally created the object and use that to submit changes.
  3. implement OnLoaded in every class and save a copy of this object that I can pass to Attach() as the baseline object.
  4. To hell with concurrency checking; load the DB version just before attaching and use that as the baseline object (NOT!!!)

选项(2)似乎是最优雅的方法,尤其是如果能找到存储到数据上下文的引用在创建对象时的方式。但是 - ?怎么样?

Option (2) seems the most elegant method, particularly if I can find a way of storing a reference to the data context when the object is created. But - how?

任何其他想法

修改

我试图按照贾森Punyon的意见,并在上表中创建一个并发字段作为测试用例。我设置了所有正确的属性(时间标记= TRUE等)在dbml的文件中的字段,我现在有一个并发场......和不同的错误:

I tried to follow Jason Punyon's advice and create a concurrency field on on table as a test case. I set all the right properties (Time Stamp = true etc.) on the field in the dbml file, and I now have a concurrency field... and a different error:

System.NotSupportedException: An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext.  This is not supported.



所以我应该在什么赫克附加,那么,如果没有一个现有的实体?如果我想要一个新的纪录,我会做一个InsertOnSubmit()! ?那么如何是你应该使用的连接()

So what the heck am I supposed to attach, then, if not an existing entity? If I wanted a new record, I would do an InsertOnSubmit()! So how are you supposed to use Attach()?

修改 - 充分披露

OK,我可以看到它的时候,充分披露的,为什么所有的标准模式不是为我工作。

OK, I can see it's time for full disclosure of why all the standard patterns aren't working for me.

我一直在试图聪明,让我接口从消费开发商隐藏在DataContext干净多了。这个我已经通过创建一个基类完成

I have been trying to be clever and make my interfaces much cleaner by hiding the DataContext from the "consumer" developers. This I have done by creating a base class

public class LinqedTable<T> where T : LinqedTable<T> {
  ...
}



...和每一个人我的表有其生成的版本中的另一半,宣布像这样:

... and every single one of my tables has the "other half" of its generated version declared like so:

public partial class MyClass : LinqedTable<MyClass> {
}

现在 LinqedTable 有一堆的实用方法,最特别的东西,如:

Now LinqedTable has a bunch of utility methods, most particularly things like:

public static T Get(long ID) {
  // code to load the record with the given ID
  // so you can write things like:
  //   MyClass obj = MyClass.Get(myID);
  // instead of:
  //   MyClass obj = myDataContext.GetTable<MyClass>().Where(o => o.ID == myID).SingleOrDefault();
}
public static Table<T> GetTable() {
  // so you can write queries like:
  //   var q = MyClass.GetTable();
  // instead of:
  //   var q = myDataContext.GetTable<MyClass>();
}



当然,你可以想像,这意味着 LinqedTable 必须以某种方式能够有机会获得一个DataContext。直到最近,我被的缓存的DataContext的在静态情况下实现这一目标。是的,直到最近,因为最近,是当我发现你不是真的要挂到一个DataContext超过一个工作单元更长,否则小鬼的种种奔涌出来的木制品。学过的知识。

Of course, as you can imagine, this means that LinqedTable must somehow be able to have access to a DataContext. Up until recently I was achieving this by caching the DataContext in a static context. Yes, "up until recently", because that "recently" is when I discovered that you're not really supposed to hang on to a DataContext for longer than a unit of work, otherwise all sorts of gremlins start coming out of the woodwork. Lesson learned.

所以,现在我知道,我不能挂在该数据上下文太久...这就是为什么我开始与需求创造一个DataContext试验,缓存仅在当前 LinqedTable 实例。这就导致了地方新创建的DataContext希望无关我的对象,因为它知道它的不忠,以创建它的DataContext的问题。

So now I know that I can't hang on to that data context for too long... which is why I started experimenting with creating a DataContext on demand, cached only on the current LinqedTable instance. This then led to the problem where the newly created DataContext wants nothing to do with my object, because it "knows" that it's being unfaithful to the DataContext that created it.

是否有推DataContext的信息到LinqedTable在创建或装载时的方法吗?

Is there any way of pushing the DataContext info onto the LinqedTable at the time of creation or loading?

这真的是一个拗造型。我绝对不希望在我已经投入了 LinqedTable 基类所有这些便利功能妥协,我需要能够让在DataContext的走在必要时挂到它,同时它还是需要的。

This really is a poser. I definitely do not want to compromise on all these convenience functions I've put into the LinqedTable base class, and I need to be able to let go of the DataContext when necessary and hang on to it while it's still needed.

任何其他的想法?

推荐答案

的实体也只能作为无原始状态修改,如果它声明版本部件安装的错误连接,有一个时间戳成员将(应该)只有在实体有发生entitity时不是过线旅行(读:被序列化和反序列化再次)。如果你正在使用未使用WCF还是其他什么东西,这将导致实体被序列化和反序列化,然后他们仍然会继续通过entitysets / entityrefs到原来的DataContext引用本地测试应用程序测试(协会/​​ NAV。属性)。

The "An entity can only be attached as modified without original state if it declares a version member" error when attaching an entitity that has a timestamp member will (should) only occur if the entity has not travelled 'over the wire' (read: been serialized and deserialized again). If you're testing with a local test app that is not using WCF or something else that will result in the entities being serialized and deserialized then they will still keep references to the original datacontext through entitysets/entityrefs (associations/nav. properties).

如果是这样的话,你可以解决它通过序列化和调用的datacontext的.Attach方法之前,本地反序列化它。例如:

If this is the case, you can work around it by serializing and deserializing it locally before calling the datacontext's .Attach method. E.g.:

internal static T CloneEntity<T>(T originalEntity)
{
    Type entityType = typeof(T);

    DataContractSerializer ser =
        new DataContractSerializer(entityType);

    using (MemoryStream ms = new MemoryStream())
    {
        ser.WriteObject(ms, originalEntity);
        ms.Position = 0;
        return (T)ser.ReadObject(ms);
    }
}



另外,您可以通过设置所有entitysets / entityrefs其分离为null,但更容易出错所以虽然有点贵的话就用DataContractSerializer的方法上面,每当我想在本地模拟n层的行为...

Alternatively you can detach it by setting all entitysets/entityrefs to null, but that is more error prone so although a bit more expensive I just use the DataContractSerializer method above whenever I want to simulate n-tier behavior locally...

(相关话题:的http:/ /social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/eeeee9ae-fafb-4627-aa2e-e30570f637ba

这篇关于你如何保存LINQ的对象,如果你没有它的数据上下文?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆