locked
ChangeInterceptor being called multiple times on Add with links RRS feed

  • Question

  • I'm using latest greatest EF4.1 with code first (DbSet) and notice that when I add a record, the ChangeInterceptor I have setup in the web service is being called multiple times presumably because the object has links set to some child objects.  Is there a way in code to tell which call is for the main object and which call is for the links - and may I ask why it is designed this way?  On Adds, my ChangeInterceptor goes out and provisions some remote equipment, and I don't want it to do that multiple times in quick succession so I'm hoping someone can help me.  Thanks!
    Friday, July 15, 2011 3:17 PM

Answers

  • Thank you for providing a repro. There are a few different things going on that led to this behavior:

    1) During request processing, the runtime builds a mapping between objects and interceptors to be fired
    2) During insert, the new object is unintentionally added to this mapping twice, once before setting the properties, and once after
    3) For 'V1'-supported providers like the entity-framework, EqualityComparer<object>.Default is used to match them up
    4) If the implementation of GetHashCode is dependent on property values, the inserted object has 2 different hash-codes in the two calls above
    5) The interceptor fires twice for the same object

    Hopefully, we will be able to address #2 in the next release so that only the fully initialized object is cached, but I cannot guarantee it will be fixed in time.

    We may also consider switching Code-First based providers to use reference equality instead of default equality (which we already do for custom providers other than EF and reflection).

    For now, if you change GetHashCode to be independent of the property values, you should be able to work around this.


    Matt Meehan (WCF Data Services / OData)
    Tuesday, July 26, 2011 7:52 PM
    Moderator

All replies

  • Can you please provide a Fiddler trace or the steps to reproduce the problem you described in above?

     

    Also, do you have multiple ChangeInterceptor targeting the same EntitySet? If that’s the case, it would be called multiple times as well.

     

    Jack Yang - MSFT

    Wednesday, July 20, 2011 6:43 PM
    Moderator
  • Hi Jack,

    Regarding the fiddler output, I don't think that is the problem as only one HTTP request is being generated and it looks correct/works - which to me means that the multiple calls are being generated somewhere in the framework, not on the client side.  I only have one ChangeInterceptor on the DbSet in question so I don't think that is it - it seems to be by design, just not sure how you are suppose to deal with it properly.  I've read in other posts from people saying that it happens when the object being added has foreign key links to other objects which mine does - for now I just worked around the problem by putting a snippet of code in to track which objects have recently been added and if it is the same one, don't call my expensive provisioning code twice in a row - not pretty but it works.

    Friday, July 22, 2011 4:17 PM
  • Hi,

    I'd really like to see the fiddler trace if you could provide it, as well as the code for your service operation and client-side operations.

    In simple cases, there's no reason the change interceptor should be firing more than once. Having the above artifacts would give us a much better sense of what is going on.

    Thanks.

    Update: If you're not comfortable posting the artifacts here, feel free to email me at 'mmeehan' at msft.


    Matt Meehan (WCF Data Services / OData)
    Monday, July 25, 2011 6:37 PM
    Moderator
  • Thank you for providing a repro. There are a few different things going on that led to this behavior:

    1) During request processing, the runtime builds a mapping between objects and interceptors to be fired
    2) During insert, the new object is unintentionally added to this mapping twice, once before setting the properties, and once after
    3) For 'V1'-supported providers like the entity-framework, EqualityComparer<object>.Default is used to match them up
    4) If the implementation of GetHashCode is dependent on property values, the inserted object has 2 different hash-codes in the two calls above
    5) The interceptor fires twice for the same object

    Hopefully, we will be able to address #2 in the next release so that only the fully initialized object is cached, but I cannot guarantee it will be fixed in time.

    We may also consider switching Code-First based providers to use reference equality instead of default equality (which we already do for custom providers other than EF and reflection).

    For now, if you change GetHashCode to be independent of the property values, you should be able to work around this.


    Matt Meehan (WCF Data Services / OData)
    Tuesday, July 26, 2011 7:52 PM
    Moderator