0

我有一個具有以下結構Unflatten數據庫記錄到主/詳細信息的EF 5碼首先

CREATE TABLE [dbo].[MASTER_PROJECT](
    [DATA_ID] [bigint] IDENTITY(1,1) NOT NULL, 
    ...... 
    [GENRE_DATA_ID] [bigint] NULL, 
    [ADDITIONAL_GENRE_DATA_ID] [bigint] NULL, 
    [ADDITIONAL_GENRE_2_DATA_ID] [bigint] NULL) 

我想有以下類映射出使用EF 5遺留數據庫表(代碼首先)

public class Project { 
    public long Id {get;set;} 
    public ICollection<Genre> Genres {get;set;} 
} 

public class Genre { 
    public long Id {get;set;} 
    // other stuff 
} 

起初我試圖使流派這樣

HasOptional(t => t.Genres[0]).WithOptionalDependent().Map(m => m.MapKey("GENRE_DATA_ID")); 
    HasOptional(t => t.Genres[1]).WithOptionalDependent().Map(m => m.MapKey("ADDITIONAL_GENRE_DATA_ID")); 
    HasOptional(t => t.Genres[2]).WithOptionalDependent().Map(m => m.MapKey("ADDITIONAL_GENRE_2_DATA_ID")); 

但這產生的陣列和映射這是一個錯誤,那t.Genres [0]不是一個有效的屬性。 (這是有道理的)

任何想法,我會如何去做這件事? 謝謝!

回答

0

與莫霍面的幫助,這裏是我最終得到我想要的。

此外,您還需要確保包含此域實體的項目授予映射項目可見的內部結構。 (在AssemblyInfo.cs中)

[assembly: InternalsVisibleTo("YOUR.MAPPING.PROJECT")] 

實體定義

public class Project 
{ 
     private ObservableCollection<Genre> _genres; 
     protected internal virtual Genre Genre1 { get; set; } 
     protected internal virtual Genre Genre2 { get; set; } 
     protected internal virtual Genre Genre3 { get; set; } 

     public IList<Genre> Genres 
     { 
      get 
      { 
       if (_genres == null) 
       { 
        _genres = new ObservableCollection<Genre>(new[] {Genre1, Genre2, Genre3}); 
        _genres.CollectionChanged += GenresCollectionChangedHandler; 
       } 
       return _genres; 
      } 
     } 
     private void SetGenreByIndex(int index, Genre g) 
     { 
      switch (index) 
      { 
       case 0: Genre1 = g; break; 
       case 1: Genre2 = g; break; 
       case 2: Genre3 = g; break; 
      } 
     } 

     private void GenresCollectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e) 
     {     
      _genres.CollectionChanged -= GenresCollectionChangedHandler; 

      int max = 3; 
      switch (e.Action) 
      { 
       case NotifyCollectionChangedAction.Add: 
        if (_genres.Count > max) 
        { 
         _genres.RemoveAt(max); 
         _genres.CollectionChanged += GenresCollectionChangedHandler; 
         throw new IndexOutOfRangeException("Not allowed to store more than 3 genres."); 
        } 
        SetGenreByIndex(_genres.Count - 1, e.NewItems[0] as Genre); 
        break; 

       case NotifyCollectionChangedAction.Replace: 
        for (var i = 0; i < e.NewItems.Count; i++) 
         SetGenreByIndex(i + e.NewStartingIndex, e.NewItems[i] as Genre); 
        break; 

       case NotifyCollectionChangedAction.Reset: 
        Genre1 = null; 
        Genre2 = null; 
        Genre3 = null; 
        _genres.Clear(); 
        break; 
      } 
      _genres.CollectionChanged += GenresCollectionChangedHandler; 
     } 
} 

這裏是代碼首先映射類

public class ProjectConfiguration 
{ 
    public ProjectConfiguration() 
    { 
     // ... 
     // GENRES collection 
     Ignore(t => t.Genres); 
     HasOptional(t => t.Genre1).WithMany().Map(m => m.MapKey("GENRE_DATA_ID")); 
     HasOptional(t => t.Genre2).WithMany().Map(m => m.MapKey("GENRE_DATA_ID_1")); 
     HasOptional(t => t.Genre3).WithMany().Map(m => m.MapKey("GENRE_DATA_ID_2")); 
    } 
} 

這裏是一個測試方法,以確保它的工作原理

[TestClass] 
public class ProjectUnitTests 
{ 
    [TestMethod] 
    public void SwapGenresInListAndSaveTest() 
    { 
     //Arrange 
     Genre original1 = null; 
     Genre original2 = null; 

     using (var context = new MyContext()) 
     { 
      context.Configuration.LazyLoadingEnabled = true; 

      //ACT 
      var project = context.Projects.Find(2341); 
      original1 = project.Genres[0]; 
      original2 = project.Genres[1]; 

      genres[0] = original2; 
      genres[1] = original1; 

      //Save to DB 
      context.SaveChanges(); 
     } 

     //ASSERT 
     using (var context = new MyContext()) 
     { 
      var project1 = context.Projects.Find(2341); 

      //ASSERT 
      Assert.IsNotNull(project1); 
      Assert.IsNotNull(project1.Genres); 
      Assert.AreEqual(3, project1.Genres.Count); 
      Assert.AreEqual(original2.DataId, project1.Genres[0].DataId); 
      Assert.AreEqual(original1.DataId, project1.Genres[1].DataId); 
     } 
    } 
} 
0

你想要做什麼與EF無關 - 你需要用一個新的方法或屬性來實現這個實體的一個部分類,這個方法或屬性返回一個這個項目的集合。當然,您需要使用各種流派數據ID屬性中的值填充此集合。例如:

public ICollection<Genre?> GenreDataIDs 
{ 
    get 
    { 
     var col = new List<Genre?>() { GENRE_DATA_ID_NavProperty, ADDITIONAL_GENRE_DATA_ID_NavProperty, ..., ADDITION_GENRE_N_DATA_ID_NavProperty }; 

     return col; 
    } 
} 

您的導航屬性可能命名爲Genre1,Genre2;爲了說明的目的,我簡單地將_NavProperty添加到列名稱中。

如果你想使用集合更新基礎數據庫記錄,它會得到更多複雜的(最簡單的實施將實現SetGenreDataID(INT指數,詮釋?value)方法)

+0

謝謝你的回答,但我還不確定我明白你在做什麼。 你是說將一個屬性GenreDataIDs添加到主Project類?那麼我將如何將這些DataID映射到關聯的映射體裁類? – NYCChris 2013-03-26 21:16:38

+0

而不是int列表?你可以返回列表;同樣的原則,您必須自己構建ICollection。我會編輯答案 – Moho 2013-03-27 00:54:39

+0

好吧,我明白你的意思了。所以Project將有4個公共屬性,Genre1,Genre2,Genre3和IList 流派。那正是我想要避免的,但我想這是沒有辦法的。 謝謝你的幫助! – NYCChris 2013-03-27 13:58:47