Cascade addition of entities

3 posts, 1 answers
  1. Alex
    Alex avatar
    7 posts
    Member since:
    Mar 2013

    Posted 03 Jun 2013 Link to this post

    I will start directly with the thing I am trying to do - the entities are the following. Document has a collection DocumentDetails and each DocumentDetail has a collection of DocumentDetailProperty entities. As I want trackable collections the code looks like this:

    // Document entity
    private TrackedBindingList<DocumentDetail> _documentDetails = new TrackedBindingList<DocumentDetail>();
    public virtual TrackedBindingList<DocumentDetail> DocumentDetails 

       get
       {
           return this._documentDetails;
       }
    }

    // DocumentDetail entity
    private TrackedBindingList<DocumentDetailProperty> _documentDetailProperties = new TrackedBindingList<DocumentDetailProperty>();
    public virtual TrackedBindingList<DocumentDetailProperty> DocumentDetailProperties 

       get
       {
           return this._documentDetailProperties;
       }
    } My
    scenario is the following: user creates a new DocumentDetail, adds some DocumentDetailProperty entities and saves all changes. The code for both the additions is:

        // adding a DocumentDetail
                DocumentDetail dd = new DocumentDetail() { DocumentId = theDoc.DocumentId };
                theDoc.DocumentDetails.Add(dd);
                context.Add(dd); // is this necessary?

       // adding a DocumentDetailProperty
                DocumentDetailProperty newDDP = new DocumentDetailProperty();
                newDDP.DocumentDetailId = SelectedDocumentDetail.DocumentDetailId; // getting id from selected item. Should handle differently when selected item is just added? It makes no difference when this line is commented 
                SelectedDocumentDetail.DocumentDetailProperties.Add(newDDP);
                context.Add(newDDP);

    Save is performed by this code:

                    context.FlushChanges();
    // just for testing - shold not matter in this scenario
                    context.ExecuteQuery<object>("uspAfterSaveTest", CommandType.StoredProcedure,
                        new OAParameter[] { new OAParameter("SomeString", "after save") });
                    context.SaveChanges();

    the profiler giving the following:

    declare @p1 int
    set @p1=NULL
    exec sp_prepexec @p1 output,N'@p0 int,@p1 int,@p2 varchar(128)',N'declare @generated_ids table([DocumentDetailPropertyId] int)
    insert [DocumentDetailProperty] ([DocumentDetailId], [PropertyId], [PropertyValue]) 
    output inserted.[DocumentDetailPropertyId] into @generated_ids 
     VALUES (@p0, @p1, @p2) 
    select t.[DocumentDetailPropertyId] 
    from @generated_ids as g join [DocumentDetailProperty] as t on g.[DocumentDetailPropertyId] = t.[DocumentDetailPropertyId] 
    where @@ROWCOUNT > 0',@p0=0,@p1=1,@p2='rewrwer'
    select @p1

    So, it tries to add only the DocumentDetailProperty entity and it fails as it tries to insert with a DocumentDetailId = 0. How can I perform both the additions with one save? Beside using TrackableCollections, I have mapping type = Xml (this was necessary in order to make TrackableCollection work, as indicated by Telerik in another thread).

    Thank you,

    Alex D.


  2. Answer
    Yordan
    Admin
    Yordan avatar
    39 posts

    Posted 05 Jun 2013 Link to this post

    Hello Alex,

    Thank you for the detailed code. The reason why you observed such behavior is because of the way how collection properties are managed. In the example code the property IsManaged of the navigation property DocumentDetailProperties is false. It should be set to true and then the child elements DocumentDetails should be added in the following way to the parent document:

    using (EntitiesModel dbContext = new EntitiesModel())
    {
        Document doc = new Document() { Name = "NameOfDoc" };
        dbContext.Add(doc);
        doc.DocumentDetails.Add(new DocumentDetail() { Name = "DocDetail1" });
        doc.DocumentDetails.Add(new DocumentDetail() { Name = "DocDetail2" });
        dbContext.SaveChanges();
    }

    This way two DocumentDetails entities will be added to the database and their DocumentId field will be set to the id of the inserted document automatically.
    More about managing navigational properties in OpenAccess ORM can be found in this article.

    Please find the attached project as an example.

    In case you encounter any more difficulties do not hesitate to get back to us.
     
    Regards,
    Yordan
    Telerik
    OpenAccess Samples Kit boasts 50+ sample applications providing diverse real-life business solutions. Click to read more and see OpenAccess ORM in action.
  3. DevCraft banner
  4. Alex
    Alex avatar
    7 posts
    Member since:
    Mar 2013

    Posted 06 Jun 2013 Link to this post

    It works very well. I have also found that setting Is Dependent = True will allow cascade delete. 

    Thanks.
Back to Top