2014-03-06 139 views
0

有問題/答案與我即將提出的問題類似,但是沒有一個人有完整的答案。 (很抱歉,如果我錯過了什麼,而搜索)實體框架多對多映射表和重複。 Code First

DB結構:

public class ApplciationDbContext : DbContext() 
{ 

    public DbSet<Photo> Photos { get; set; } 
    public DbSet<Tag> Tags { get; set; } 
    public DbSet<Tag_Photo_XREF> TagPhoto_XREF { get; set; }  

} 

public abstract class BaseEntity 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public Guid Id { get; set; } 
} 

public class Tag : BaseEntity 
{ 
    public Tag() 
    { 
     Photos = new HashSet<Tag_Photo_XREF>(); 
    } 
    public string TagText { get; set; } 
    public virtual ICollection<Tag_Photo_XREF> Photos { get; set; } 
} 

public class Tag_Photo_XREF : BaseEntity 
{ 
    public Guid TagId { get; set; } 
    public Guid PhotoId { get; set; } 
    public int Score { get; set; } 
    public virtual Tag Tag { get; set; } 
    public virtual Photo Photo { get; set; } 
} 

public class Photo : BaseEntity 
{ 
    public Photo() 
    { 
     Tags = new HashSet<Tag_Photo_XREF>(); 
     GeneratedTags = new HashSet<GeneratedTag_Photo_XREF>(); 
    } 

    public virtual ICollection<Tag_Photo_XREF> Tags { get; set; }   

    } 
} 

我看到這一切是如何掛在一起,但我的問題是: 1)如何防止標籤重複插入主。 2)如何在第一個地方插入?我該怎麼辦:

Photo p = new Photo(); 
Tag_Photo_XREF tagPhotoXref1 = new Tag_Photo_XREF(); 
tagPhotoXref1.Tag = new Tag() { TagText = "...1" }; 

Tag_Photo_XREF tagPhotoXref2 = new Tag_Photo_XREF(); 
tagPhotoXref2.Tag = new Tag() { TagText = "...2" }; 

Tag_Photo_XREF tagPhotoXref3 = new Tag_Photo_XREF(); 
tagPhotoXref3.Tag = new Tag() { TagText = "...3" }; 
p.Tags.Add(tagPhotoXref1); 
p.Tags.Add(tagPhotoXref2); 
p.Tags.Add(tagPhotoXref3); 

dbContext.Photos.Add(p); 
dbContext.SaveChanges(); 

或類似的東西:

Photo p = new Photo(); 
Tag_Photo_XREF tagPhotoXref1 = new Tag_Photo_XREF(); 
tagPhotoXref1.Tag = new Tag() { TagText = "...1" }; 
tagPhotoXref1.Photo = p; 

Tag_Photo_XREF tagPhotoXref2 = new Tag_Photo_XREF(); 
tagPhotoXref2.Tag = new Tag() { TagText = "...2" }; 
tagPhotoXref1.Photo = p; 

Tag_Photo_XREF tagPhotoXref3 = new Tag_Photo_XREF(); 
tagPhotoXref3.Tag = new Tag() { TagText = "...3" }; 
tagPhotoXref1.Photo = p; 

dbContext.TagPhoto_XREF.Add(tagPhotoXref1); 
dbContext.TagPhoto_XREF.Add(tagPhotoXref2); 
dbContext.TagPhoto_XREF.Add(tagPhotoXref3); 
dbContext.Photos.Add(p); 
dbContext.SaveChanges(); 

兩種方式都顯得很凌亂和過於複雜。如果我不需要鏈接表上的Score屬性,這將會非常不同。

關於這一點的另一個問題是,如果我必須從如何可以防止相同的標記作爲嵌入不同的用戶我ApplicationDbContext多個連接(文字必須是唯一的)

也許我錯過了點方式複雜化。

感謝

史蒂夫

+0

這個示例是嗎?在'Photo'實體中,您有'GeneratedTags = new HashSet ();'但我看不到'GeneratedTags'屬性。 – Leron

+0

@Leron是的,我複製這個並刪除了很多其他的屬性..ignore在ctor它只是無關。 –

回答

0

通常當你有其他的兩個表之間的外部參照表,你不使用的身份/代理主鍵。外部參照的主鍵是兩個實體鍵的複合鍵:在你的情況下它將是TagId,PhotoId

現在考慮你正在使用BaseEntity將主鍵定義爲所有實體的標識,沒有那種奢侈(除非你改變你的代碼)。我能看到的唯一解決方案就是在這兩列上放置一個唯一的索引(可以使用遷移來完成)。另一種選擇只是爲了防止在應用程序中使用業務邏輯的重複。

對於您的其他問題,你通常會做這樣的事情:

Photo p = new Photo(); 
Tag tag1 = new Tag() { ... }; 
Tag tag2 = new Tag() { ... }; 

p.Tags.Add(new Tag_Photo_XREF { Tag = tag1 }; 
p.Tags.Add(new Tag_Photo_XREF { Tag = tag2 }; 

context.Photos.Add(p); 
context.SaveChanges(); 

你並不需要直接添加標籤和外部參照上下文,因爲它正在通過您所定義的關係增加。

你也許可以通過增加輔助方法你的照片讓類對自己這更容易:

public class Photo 
{ 
    // ... 

    public void AddTag(Tag tagToAdd) 
    { 
     this.Tags.Add(new Tag_Photo_XREF { Tag = tagToAdd }); 
    } 

    // ... 
} 

,將採取爲您創造外部參照部分的護理。

+0

多數民衆贊成它回答了我的一半問題。現在爲了防止重複,我可以很容易地從一個DBContext中處理它,但是如果有50,100,1000個操作都在同一時間進行,那麼如何確保重複標記不會被添加?從單個DBContext執行它可以,因爲您可以檢查更改跟蹤器等。我可能需要問一個單獨的問題? –

+0

我會問這是一個單獨的問題。謝謝 –

+0

我在答案中提到...你可以添加一個唯一的索引到你的數據庫。如果您嘗試插入重複項,這會引發錯誤。 – Dismissile