Delete, Flush, and Requey

4 posts, 0 answers
  1. Paul
    Paul avatar
    17 posts
    Member since:
    May 2011

    Posted 04 Dec 2014 Link to this post

    Hi again,

    I'm trying to write some automated integration tests against my database objects, using Telerik Q2 2014 SP1.

    The general form of a test is like this:

    using (var context = new MyContext())
    {
        // Create any related objects necessary for test
        context.FlushChanges();
     
        var entityUnderTest = new Entity();
        context.Add(entityUnderTest);  // Or update, or delete - whatever I'm testing.
        context.FlushChanges();
        context.Refresh(RefreshMode.OverwriteChangesFromStore, entityUnderTest);
     
        // Asserts, etc.
        context.ClearChanges();
    }

    I'm inside of a transaction and using FlushChanges() so that I get a full cleanup if the test fails.  This has worked great - except for one type of entity:

    using (var context = new MyContext())
    {
        // Create individual, organization, membership...
        context.FlushChanges();
     
        var entity = context.GetAll<Membership>()
            .Where(i => i.MemberId == individualId && i.MemberOfId == organizationId).Single();
        context.Delete(entity);
        context.FlushChanges();
      
        var deletedEntity = context.GetAll<Membership>()
            .Where(i => i.MemberId == individualId && i.MemberOfId == organizationId).SingleOrDefault();
        Assert.IsNull(deletedEntity);
      
        context.ClearChanges();
    }


    This is the only entity in my model with a composite key - a cross-reference table with some extra columns.  When I trace this at the database layer, the delete is executed (it happens to be a stored procedure), but the context doesn't re-query the database to assert the record was deleted.  The deletedEntity variable contains a reference to the entity.  They are both in the "Deleted" state, and attempts to access any properties throws an exception - as expected! - but I am used to getting a null back from the final SingleOrDefault() query.

    Any advice on what I might be doing wrong?
  2. Kaloyan Nikolov
    Admin
    Kaloyan Nikolov avatar
    118 posts

    Posted 09 Dec 2014 Link to this post

    Hi Paul,

    The described behavior is by design. All entities are still accessible in the context with their updated states, if you have an updated entity it will stay tracked by the context in updated state, the same applies for the deleted entities. If you execute a query and a deleted entity fulfills the where clause it will be returned in deleted state. When the SaveChanges()/ClearChanges() is called all states will be applied and the deleted entities will not be deleted any more. 

    Unfortunately there is no way to change the above behavior. You could write alternative AssernNullEntity method which will handle both cases - checking if it is null or if not it should be in deleted state. 

    Should you have any additional questions do not hesitate to get back to us. 

    Regards,
    Kaloyan Nikolov
    Telerik
     
    OpenAccess ORM is now Telerik Data Access. For more information on the new names, please, check out the Telerik Product Map.
     
  3. DevCraft banner
  4. Paul
    Paul avatar
    17 posts
    Member since:
    May 2011

    Posted 09 Dec 2014 in reply to Kaloyan Nikolov Link to this post

    Hi Kaloyan,

    I understand why this would be expected behaviour, given how Telerik must cache the local objects.  Can you confirm that I should be inconsistent results based on the complexity of the keys?  It seems to vary based on the number of keys in the query:

    // Find and delete with both PKs
    // Test with both PKs
    var deletedEntity = unitOfWork.GetAll<Membership>()
        .Where(i => i.MemberId == individualId && i.MemberOfId == organizationId).SingleOrDefault();
    Assert.IsNull(deletedEntity);  // Fails, per above
     
    // Find and delete with both PKs, test result with only one
    var deletedEntity = unitOfWork.GetAll<Membership>()
        .Where(i => i.MemberId == individualId).SingleOrDefault();
    Assert.IsNull(deletedEntity);  // Succeeds?
     
    // Different object - only has one PK.
    // Find and delete with PK, test with PK.
    var deletedEntity = unitOfWork.GetAll<Individual>()
        .Where(i => i.Id = individualId).SingleOrDefault(); // Using the only PK on the object
    Assert.IsNull(deletedEntity); // Succeeds?


  5. Kaloyan Nikolov
    Admin
    Kaloyan Nikolov avatar
    118 posts

    Posted 12 Dec 2014 Link to this post

    Hello Paul,

    Your first example is expected to fail as you query the object by its Id and it is loaded in the context. 
    The second succeeds because not all PKs are used in the query and thus it is executed against the DB as such query could return more than one entity.
    For the third example it is supposed to fail too. You can validate this with the attached sample application. If that is not working for you then should be something with the setup or with the usage. Could you please send the exact code how you find and delete the entity plus the mapping.

    To be able to attach the requested files I've converted your ticket to Product Feedback. 

    Looking forward for your additional input.

    Regards,
    Kaloyan Nikolov
    Telerik
     
    OpenAccess ORM is now Telerik Data Access. For more information on the new names, please, check out the Telerik Product Map.
     
Back to Top