![](/img/trans.png)
[英]Querying or Merging One-to-Many Relationship without Duplicating Entries of the Result
[英]Creating copy of entities with many to many relationship without duplicating one of the type
我在復制具有多對多關系的實體時遇到問題。 我有三個實體Company , Role和User定義如下:
公司:
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
。 沒錯,圖中的所有實體都將恰好代表一個“真實”實體。
但是,在您的情況下, User
和Roles
之間存在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.