Entities from GetAll<T> not returned until AFTER SaveChanges() is called

3 posts, 0 answers
  1. Mark
    Mark avatar
    2 posts
    Member since:
    Apr 2014

    Posted 03 Jul 2015 Link to this post

    I am trying to incorporate Telerik Data Access (using SQLite) into some new development.

    One of the requirements is to try to insert data into a table, but only if it does not already exist (using a Unique "Code" value to check the existence, rather than the PK id).

    The plan was to use the DataContext as a transaction, so that multiple records can be committed at once, and easily roll backed if an error occurs.

    For this to work, the entities to be inserted need to be queried along with the entities already in the database.

     

    I was under the assumption that this is a standard feature of an ORM, and was expecting this to work straight out of the box. Am I missing a setting or something?

     

    Here's some code that may help explain what I'm talking about:

    [TestMethod]
    public void when_a_record_is_inserted_it_should_be_retrievable_BEFORE_save_changes_is_called()
    {
        var testTable = new TestTable()
        {
            Id = 1,
            UniqueValue = "Test",
            OtherValue = "Testing 123"
        };
     
        using (var dataContext = new TestFluentModel.TestFluentModel())
        {
            dataContext.Add(testTable);
     
            var toBeInserted = dataContext.GetChanges().GetInserts<TestTable>().SingleOrDefault(x => x.UniqueValue == "Test");
            Assert.IsNotNull(toBeInserted); //THIS WORKS, BUT WOULD MEAN ALL MY "GETS" WOULD NEED TO SEARCH THIS AS WELL AS GETALL
     
            var contextOnlyRecord = dataContext.GetAll<TestTable>().SingleOrDefault(x => x.UniqueValue == "Test");
            Assert.IsNotNull(contextOnlyRecord); //THIS FAILS
     
            dataContext.SaveChanges();
     
            var dbRecord = dataContext.GetAll<TestTable>().SingleOrDefault(x => x.UniqueValue == "Test");
            Assert.IsNotNull(dbRecord); //THIS WOULD WORK, BUT ONLY BECAUSE THE RECORD IS NOW IN THE DB
        }
    }

     

     

  2. Mark
    Mark avatar
    2 posts
    Member since:
    Apr 2014

    Posted 03 Jul 2015 in reply to Mark Link to this post

    After a lot of searching in your forum, I think I may have just solved this.

    From this post back in 2011

    http://www.telerik.com/forums/transaction-handling

     

    The suggesting is to user

    dataContext.FlushChanges();

    After dataContext.Add(T) is called.

     

    This has solved my problem, but I'd still like some confirmation that this is the correct solution? 

    Is there not a setting to force a Flush after exery Add/Update/Delete?

     

     

  3. DevCraft banner
  4. Simeon Simeonov
    Admin
    Simeon Simeonov avatar
    24 posts

    Posted 08 Jul 2015 Link to this post

    Hi Mark,

    Thank you for contacting us.

    The first thing you need to know is that the Add() method does not open a transaction to the database. If you want to send the pending data to the database you need to execute FlushChanges() or SaveChanges().

    For your particular case if you want to use FlushChanges() you will need to:
    1/ Set the context IsolationLevel to IsolationLevel.ReadUncommitted in order for the GetAll() method to get also the newly added records (instead of only those that are in the database). For more details you can read this article.
    2/ Call FlushChanges() after every Add() call.

    This approach is not ideal for the performance of your application.

    Your initial approach of checking not only with GetAll(), but also checking the pending inserts (with .GetChanges().GetInserts()) is preferable. It is better to check the pending inserts after each Add() then calling FlushChanges() after each Add(). For this reason I would recommend that you use this approach.

    I would also recommend that you add a database unique constraint for the "UniqueValue" column. This will add validation on the database level that you don't create records with the same value in this column. For more details you can see this article and more specifically the use of the IsUnique().

    I hope you find this information helpful.

    Regards,

    Simeon Simeonov
    Telerik
     
    Check out the latest announcement about Telerik Data Access vNext as a powerful framework able to solve core development problems.
Back to Top