none
How to find out if entity is already attached to DataContext or loaded by another DataContext RRS feed

  • Question

  • Linq to SQL. VS2010.

    I use the Attach method to attach and update entities coming back from client over WCF. This works fine.

    However if I run Unit Test on the data access layer I get the '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.'. This is correct, the unit test gets the entity directly from the data access layer and it is not detached.

    So far I use helper method to detach (serialize/deserialize) the entity in my Unit Test class before I call the data access but this solution is not scalable.

    The DataContext knows that the entity is already loaded/attached to another DataContext. How do I find the same???

    I want to execute a method in my data access class and if the entity is loaded by another data context I will detach it so I can safely attach and update it.

    Thank you.

    Tuesday, July 20, 2010 9:19 PM

Answers

  • Hello Lingzhi,

    I read those links and more most of the afternoon yesterday and I posted the question with the hope that there is solution to this.

    I use SqlMetal to generate the dbml. I don’t want to modify it after that. Otherwise it becomes un-maintainable once the number of entities grows. If the database changes I run SqlMetal and then run my unit tests. If the database changes caused unit test to break I fix it and this is it, straightforward and simple.

    How very short-sighted from the team that created LINQ to SQL. From one side they advise to use the data context as short life unit of work, which I understand as reading the entities in one data context, do something with them and then update them in a different data context. And it makes perfect sense. However this only works out of the box if I use WCF. We are talking about N-Tier applications. May be I assume wrong but N could stand for 1 or 4. Why are those cases supported in different ways?

    Short answer is I cannot use LINQ to SQL seamlessly with and without WCF. I must have two different data access layers. That doesn’t make much sense.

    I can work around the problem but I was really hoping this is built in. The best idea I have so far is to add a boolean ‘detach’ flag to my data access methods (true => detach before attach). I don’t want to rely on exceptions for this kind of logic.

    Thanks anyway.

     

     

    Wednesday, July 21, 2010 2:14 PM

All replies

  • Hello,

     

    Welcome to LINQ to SQL forum!

     

    It’s recommended to first detach the entity before attaching them.   Based on the MSDN document for Table(TEntity).Attach, http://msdn.microsoft.com/en-us/library/bb300517.aspx:

     

    Do not try to Attach an entity that has not been detached through serialization. Entities that have not been serialized still maintain associations with deferred loaders that can cause unexpected results if the entity becomes tracked by a second data context.

     

    I checked the implementation of how LINQ to SQL verify the associations with deferred loaders.   The logic is very complicated and it’s realized in some internal classes like System.Data.Linq.ChangeTracker.   So it is hard for us to call these internal methods to check if the certain entity is tracked by another context.    

     

    I would recommend detach the entities via serialization first.   Or you may consider call .Attach method on the entity and if the certain NotSupportedException is caught, we then detach the entity. 

     

    Additional references about LINQ to SQL detaching entities:

    http://geekswithblogs.net/michelotti/archive/2007/12/25/117984.aspx

    http://geekswithblogs.net/michelotti/archive/2007/12/27/118022.aspx

     

    Good day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Wednesday, July 21, 2010 6:38 AM
    Moderator
  • Hello Lingzhi,

    I read those links and more most of the afternoon yesterday and I posted the question with the hope that there is solution to this.

    I use SqlMetal to generate the dbml. I don’t want to modify it after that. Otherwise it becomes un-maintainable once the number of entities grows. If the database changes I run SqlMetal and then run my unit tests. If the database changes caused unit test to break I fix it and this is it, straightforward and simple.

    How very short-sighted from the team that created LINQ to SQL. From one side they advise to use the data context as short life unit of work, which I understand as reading the entities in one data context, do something with them and then update them in a different data context. And it makes perfect sense. However this only works out of the box if I use WCF. We are talking about N-Tier applications. May be I assume wrong but N could stand for 1 or 4. Why are those cases supported in different ways?

    Short answer is I cannot use LINQ to SQL seamlessly with and without WCF. I must have two different data access layers. That doesn’t make much sense.

    I can work around the problem but I was really hoping this is built in. The best idea I have so far is to add a boolean ‘detach’ flag to my data access methods (true => detach before attach). I don’t want to rely on exceptions for this kind of logic.

    Thanks anyway.

     

     

    Wednesday, July 21, 2010 2:14 PM
  • I did see a piece of code that took an entity and looked at a private property via reflection.  This property had a property that was the DataContext.  You just had to make sure the two DataContext instances where the same.  It did work in Framework 3.5, but did not in Framework 4.0.

    You say serialize is not scalable.  If you are just testing one row Linq Entities have the attribute "Column" on properties that are columns.  You can use reflection and created a new detached object and copy all the columns from one object to the other.

    Wednesday, July 21, 2010 3:46 PM