Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BulkInsert does not populate foreign keys for child entities #95

Closed
jaybz opened this issue Nov 14, 2018 · 3 comments
Closed

BulkInsert does not populate foreign keys for child entities #95

jaybz opened this issue Nov 14, 2018 · 3 comments
Labels

Comments

@jaybz
Copy link

jaybz commented Nov 14, 2018

I have an set of POCOs that are set up like this:

public class Parent {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public long ParentID { get; set; }

        [ForeignKey("ChildAID")]
        public ChildA ChildA { get; set; }

        [ForeignKey("ChildBID")]
        public ChildB ChildB { get; set; }
}

public class ChildA {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public long ChildAID { get; set; }

        [ForeignKey("ChildBID")]
        public virtual ChildB ChildB { get; set; }
        public long? ChildBID { get; set; }

        public string SomeProperty { get; set; }
}

public class ChildB {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public long ChildBID { get; set; }

        public string SomeProperty { get; set; }
}

My problem is that when using BulkInsert on Parent entities that have existing ChildA and ChildB entities, the keys for ChildA and ChildB are not populated on the Parent's table. My code does something like this:

var children = context.ChildA.Where(c => c.SomeProperty.Equals("somestring"));
var parentsToCreate = new List<Parent>();
foreach(var child in children) {
        parentsToCreate.Add(new Parent { 
                ChildA = child,
                ChildB = child.ChildB
        });
}
dataMatchingContext.BulkInsert(parentsToCreate);

This does insert to the Parent table, but both ChildAID and ChildBID is null. Replacing the BulkInsert call with the code below populates both child IDs properly but is obviously slow.

dataMatchingContext.AddRange(parentsToCreate)
dataMatchingContext.SaveChanges();
@borisdj
Copy link
Owner

borisdj commented Nov 14, 2018

For FKs in BULK you need FKId Properties in Parent class:
([ForeignKey] Attributes are not required if FKId Properties are named by convention ChildNavProp + 'ID'/'Id')

public class Parent
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long ParentID { get; set; }
    
    //[ForeignKey("ChildAID")]
    public ChildA ChildA { get; set; }
    public long ChildAID { get; set; }
    
    //[ForeignKey("ChildBID")]
    public ChildB ChildB { get; set; }
    public long? ChildBID { get; set; }
}

And you need to set them as well.

new Parent
{
    ChildA = child,
    ChildB = child.ChildB,
    ChildAID = child.ChildAID,
    ChildBID = child.ChildBID
}

Also if you don't need to use Navigation Properties you don't have to set them, you could just have:

new Parent
{
    ChildAID = child.ChildAID,
    ChildBID = child.ChildBID
}

@jaybz
Copy link
Author

jaybz commented Nov 14, 2018

Is there no way to make it work without exposing the IDs? I don't actually need any of the IDs but I do need the navigation properties in my model.

@borisdj
Copy link
Owner

borisdj commented Nov 14, 2018

In that case, keep Navigation but add IDs also to Entity.

I find it good practice to always have explicit IDs.
One benefit is you can reference ID directly 'parent.ChildID' instead of parent.Child.ChildID.
Second is you sometimes need them explicit if ColumnName would be different from PropertyName.
And direct ID is more practical for writing Linq Join-s.

Anyway in the library column is mapped with the Property and Navigation props. are ignored.
Theoretically FK property could be dynamically created from Nav. property (similar as EF is doing it) but I am not sure how that would be implemented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants