2013-12-17 85 views
6

我正在開發我的第一個實體框架應用程序。我使用EF vesion 6(來自Nuget)和.net 4.0。但是,對於我來說,我遇到了一些困難,看起來應該非常簡單。我在互聯網上發現了很多相互矛盾的建議和解決方案,但花了幾天的時間努力解決問題後,我感到非常困惑,並且質疑我對Entity Framework的一些基本理解。我想要做的是:創建一個相關實體的簡單集合,並在它們從父代中移除時自動刪除它們。實體框架6和集合

下面是我將如何在香草C#中建模。在與微軟的樣本保持一致,假設我們有兩個類,郵政和標籤,就像這樣:

public class Post 
{ 
    public string Name { get; set; } 
    public string Author { get; set; } 

    public ICollection<Tag> Tags { get; set; } 
} 

public class Tag 
{ 
    public string Text { get; set; } 
    // Possibly other properties here 
} 

然後,添加標籤爲myPost.Tags.Add(myTag)簡單和移除標籤是myPost.Tags.Remove(myTag)一樣簡單。

現在到實體框架的一面:我看着那個,想到「外鍵,當然!」但是我添加FK時遇到了一系列問題:從數據庫中刪除標記時,標記不會從數據庫中刪除,myPost.Tags從數據庫加載時將有0個元素,儘管SQL Explorer顯示PostId值是正確的,等我擺了一堆技巧,如標記Tag.PostId作爲一個關鍵,手動刪除標籤,實際上添加標籤到上下文作爲一個DbSet,手動設置myTag.Post = null;(我試着懶惰加載啓用和禁用,它是什麼值得 - 雖然我想保持它如果可能的話)

現在(感謝在看似矛盾和過於複雜的例子不小),我很困惑和迷失。有人能告訴我如何在EF中設置這種關係嗎? (我使用代碼首先,順便說一下)

SOLUTION:

感謝莫霍面,我想出了這個結構,這不正是我想要的東西:

public class Post 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Author { get; set; } 

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

    public Post() 
    { 
     Tags = new HashSet<Tag>(); 
    } 
} 

public class Tag 
{ 
    [Key, Column(Order=1), DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 
    public string Text { get; set; } 
    // Possibly other properties here 

    public virtual Post Post { get; set; } 
    [Key, Column(Order=2)] 
    public virtual int PostId { get; set; } 
} 

public class TestContext : DbContext 
{ 
    public DbSet<Post> Posts { get; set; } 
} 

當一個TagPost的標籤集合中刪除,實體框架將發出一個刪除標記,如這裏概述(#2):http://www.kianryan.co.uk/2013/03/orphaned-child/

同樣,添加標籤後會自動發出INSERT和設置FK關係臀部。

有一點需要注意:確保您使用virtual!我認爲這也是我很多挫折的根源。

+0

你沒有把'Id'屬性和EF做關係?你能否給我們一個你如何做你的查詢的例子? – Tico

+0

@Tico我遺漏了EF實現的東西,這是故意的 - 我想避免從我的實際實現中產生任何負面影響/先入之見(更不用說它改變了很多,因爲我擺弄它!),以便我可能能夠從一開始就獲得關於如何設置它的建議。同樣的故事與我的示例查詢,但我想我的使用情況是這樣的:「1)使用一些初始標籤創建的帖子2)發佈的標籤進行編輯,刪除一些,添加一些3)郵政已保存。 – Xcelled194

+0

所以我猜你對上下文和東西很熟悉。由於你在SQL中有一些數據。使用LINQ來查詢其中的一個。如果它仍然返回'null',那麼查詢可能有問題。 – Tico

回答

2

也嘗試定義Tag方面的關係,指定每個Tag涉及單個Post並且是必需的。

所需導航性能在Tag添加到Post

public class Tag 
{ 
    // you need an ID 
    public int Id { get; set; } 

    public string Text { get; set; } 

    [Required] 
    public virtual Post Post { get; set; } 
} 

或者,如果你真的不想要添加的導航屬性,你可以使用流利的API:

modelBuilder.Entity<Post>().HasMany(p => p.Tags).WithRequired(); 
+0

我通常爲導航屬性添加一個「Id」。 – Tico

+0

我的意思是你需要一個主鍵ID字段爲你的實體;假設您爲了簡潔而將它們排除在外 – Moho

+0

'[必需的]'DataAnnotation用於創建所需的關係。我的意思是'公共虛擬Post Post {get;組; }'還有一個屬性:'public int PostId {get;組; }'。當我搜索一個對象時,我只有'Id'。如果我搜索'Post',它會返回'null' – Tico

0

這可能是線程死靈,但我沒有代表評論。以下不會做你需要的嗎?

public class Tag 
{ 
    [Key, Column(Order=1), DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 
    public string Text { get; set; } 
    // Possibly other properties here 

    public int PostId { get; set; } 

    [ForeignKey("PostId")] 
    public virtual Post Post { get; set; } 

} 

PostId從數據庫中加載,然後用作外鍵(通過註釋)到Post類中。郵政是虛擬的,沒有別的。你可能也只需要使用基本的[Key]註釋。

+0

EF自動識別一個名爲'ID'的屬性作爲一個類的唯一標識符,所以你是多餘的。此外,Fluent API在描述關係方面似乎比裝飾物更好(更可靠)。此外,在DbContext中定義您的關係(以及其他數據訪問層文件中的其餘持久性描述)可以讓您稍後離開EF,只需進行一些更改。 –