linq2db / linq2db.EntityFrameworkCore

Bring power of Linq To DB to Entity Framework Core projects
MIT License
462 stars 38 forks source link

How to include related entities with `BulkCopy`? #243

Closed michaldivis closed 2 years ago

michaldivis commented 2 years ago

Hi, I'd like to know if it's possible to also copy any related entities when using the BulkCopy extension method.

Here's my use case:

public class User
{
    [Key]
    public Guid UserId { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }

    public List<string> Claims { get; set; } = new List<string>();

    public User Employer { get; set; }

    public List<User> Employees { get; set; } = new List<User>();
}

public class Order
{
    [Key]
    public Guid OrderId { get; set; }
    public DateTime Created { get; set; }

    public User Creator { get; set; }
    public User AssignedHandler { get; set; }
    public List<OrderState> States { get; set; } = new List<OrderState>();
}

public class OrderState
{
    [Key]
    public Guid OrderStateId { get; set; }

    public User CreatedBy { get; set; }

    public DateTime Timestamp { get; set; }
    public OrderStatus Status { get; set; }
    public string Message { get; set; }
}

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum OrderStatus
{
    Created = 1,
    Processing = 2,
    Canceled = 3,
    Completed = 4
}

Here's how I'm trying to copy the data:

  1. This doesn't work (doesn't copy any relations - i.e. Order's relation to it's Creator)
MyDbContext _db;

var options = new BulkCopyOptions { 
    KeepIdentity = true
};

_db.BulkCopy(options, _db.Users.AsEnumerable());
_db.BulkCopy(options, _db.Orders.AsEnumerable());
_db.BulkCopy(options, _db.OrderStates.AsEnumerable());
  1. This doesn't work either (doesn't copy any relations - i.e. Order's relation to it's Creator)
MyDbContext _db;

var options = new BulkCopyOptions { 
    KeepIdentity = true
};

var data = _db.Orders
    .Include(a => a.Creator)
    .Include(a => a.AssignedHandler)
    .Include(a => a.States)
    .AsEnumerable()

_db.BulkCopy(options, var data = _db.Orders);

Is there a way to achieve this?

sdanyliv commented 2 years ago

How do you check that relations are not copied? If three tables are successfully copied then you ca load records with relations.

sdanyliv commented 2 years ago

OMG, sorry, we cannot copy this. You have shadow properties, which extension cannot see. If you want to copy table via this extension, you have to expand your classes.

public class User
{
    [Key]
    public Guid UserId { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }

    public List<string> Claims { get; set; } = new List<string>();

    public Guid EmployerId { get; set; }
    public User Employer { get; set; }

    public List<User> Employees { get; set; } = new List<User>();
}

public class Order
{
    [Key]
    public Guid OrderId { get; set; }
    public DateTime Created { get; set; }

    public Guid CreatorId { get; set; }
    public User Creator { get; set; }

    public Guid AssignedHandlerId { get; set; }
    public User AssignedHandler { get; set; }

    public List<OrderState> States { get; set; } = new List<OrderState>();
}

public class OrderState
{
    [Key]
    public Guid OrderStateId { get; set; }

    public Guid CreatedById { get; set; }
    public User CreatedBy { get; set; }

    public DateTime Timestamp { get; set; }
    public OrderStatus Status { get; set; }
    public string Message { get; set; }
}
michaldivis commented 2 years ago

@sdanyliv Thanks so much, that's what I've been missing.