簡體   English   中英

創建具有多對多關系的實體副本,而無需復制其中一種類型

[英]Creating copy of entities with many to many relationship without duplicating one of the type

我在復制具有多對多關系的實體時遇到問題。 我有三個實體CompanyRoleUser定義如下:

公司:

public class Company
{
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual IList<User> Users { get; set; }
}

用戶:

public class User
{
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual IList<Role> Roles { get; set; }
}

角色:

public class Role
{
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual IList<User> Users { get; set; }
}

另外,我定義了用戶和角色之間的多對多關系:

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        ToTable("TUser");
        HasKey(x => x.Id);

        HasMany(x => x.Roles).WithMany(x => x.Users).Map(m =>
        {
            m.MapLeftKey("UserId");
            m.MapRightKey("RoleId");
            m.ToTable("TUserRole");
        });
    }
}

我使用遷移在db中創建表,顯然使用EF創建了表TUserRole(到目前為止一切正常)。

現在,我想創建公司和用戶的副本,但不復制角色(因此,我想在表TCompany,TUser和TUserRole上創建新記錄,但在TRole上沒有新記錄)。

我以為這樣的事情會奏效,但我遇到了例外:

Context context = new Context();

var company = context.Companies.Include(x => x.Users.Select(u => u.Roles)).AsNoTracking().SingleOrDefault();

context.Companies.Add(company);

foreach (var user in company.Users)
{
    foreach (var role in user.Roles)
    {
        context.Entry(role).State = EntityState.Unchanged;
    }
}

context.SaveChanges();

例外是保存或接受更改失敗,因為多個“ Mackas.EF.Model.Role”類型的實體具有相同的主鍵值。

我知道為什么要得到這個(因為有多個具有相同ID的角色),但是我不知道應該采用什么方法。

有什么建議么?

我正在使用EF 6.1.3。

通常,使用AsNoTracking是獲取未附加到上下文的實體圖的好主意。 如您所知,將根實體( company )添加到新的上下文中會將圖形中的所有實體標記為“已Added ,復制實體簡直是小菜一碟。

但是,有一個令人討厭。 AsNoTracking導致EF為結果集中的每個實體實例化一個新對象,因為它無法跟蹤某個實體已經實例化。 因此,只要對象圖僅偏離根實體,就可以。 即,只要所有關聯均為1 - 0..n 沒錯,圖中的所有實體都將恰好代表一個“真實”實體。

但是,在您的情況下, UserRoles之間存在m - n關聯。 該圖收斂 如果某些用戶具有相同的角色,則在使用AsNoTracking時,EF將創建重復的Role對象。

[順便說一句,與AsNoTracking相反,即使使用AsNoTracking ,EF-core也可以創建唯一的實體]

此處的方法是通過一個上下文(即POCO,而不是代理)查詢對象圖,然后將其添加/附加到第二個上下文:

Company company;
using (Context context = new Context())
{
    context.Configuration.ProxyCreationEnabled = false;
    company = context.Companies.Include(x => x.Users.Select(u => u.Roles))
                     .SingleOrDefault();
}

using (Context context = new Context())
{
    context.Companies.Add(company);

    foreach (var user in company.Users.SelectMany(u => u.Roles)
                                .Distinct())
    {
        context.Entry(role).State = EntityState.Unchanged;
    }

    context.SaveChanges();
}

代理引用了創建它們的上下文,因此您不能將它們附加到第二個上下文。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM