2014-06-30 65 views
0

我在從我的數據實體創建業務實體時遇到了很多麻煩。使用自我導航屬性映射數據實體到業務實體

Github

Data.Entities.User如下所示:

public class User 
{ 
    public User() 
    { 
     Messages = new List<Message>(); 
     Followers = new List<User>(); 
     Favorites = new List<Message>(); 
     Notifications = new List<Notification>(); 
     SubscribedTopics = new List<Topic>(); 
    } 

    public string Id { get; set; } 
    public string Name { get; set; } 
    public string Email { get; set; } 
    public string Tag { get; set; } 
    public string Picture { get; set; } 

    public ICollection<Message> Messages { get; set; } 
    public ICollection<User> Followers { get; set; } 
    public ICollection<Message> Favorites { get; set; } 
    public ICollection<Notification> Notifications { get; set; } 
    public ICollection<Topic> SubscribedTopics { get; set; } 

} 

Data.Mappers.UserMapper看起來是這樣的:

class UserMapper : EntityTypeConfiguration<User> 
{ 
    public UserMapper() 
    { 
     // Table Mapping 
     ToTable("Users"); 

     // Primary Key 
     HasKey(u => u.Id); 
     Property(u => u.Id) 
      .IsRequired(); 

     // Properties 
     Property(u => u.Name) 
      .IsRequired() 
      .HasMaxLength(140); 

     Property(u => u.Email) 
      .IsRequired() 
      .HasMaxLength(255) 
      .IsUnicode(false); 

     Property(u => u.Tag) 
      .IsRequired() 
      .IsUnicode(false) 
      .HasMaxLength(255) 
      .HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute())); 

     Property(u => u.Picture) 
      .IsOptional(); 

     // Relationships 
     HasMany(u => u.Followers) 
      .WithMany() 
      .Map(u => u.MapLeftKey("FollowerID")); 

     HasMany(u => u.Favorites) 
      .WithMany() 
      .Map(u => u.MapLeftKey("MessageID")); 

     HasMany(u => u.SubscribedTopics) 
      .WithMany(t => t.Subscribers) 
      .Map(u => 
      { 
       u.ToTable("TopicSubscribers"); 
       u.MapLeftKey("UserID"); 
       u.MapRightKey("TopicID"); 
      }); 
    } 
} 

最後,我Domain.Entities.User這樣的:

public class User : EntityBase<string> 
{ 
    public string Name { get; set; } 
    public string Email { get; set; } 
    public string Tag { get; set; } 
    public string Picture { get; set; } 
    public IEnumerable<Message> Messages { get; set; } 
    public IEnumerable<User> Followers { get; set; } 
    public IEnumerable<Message> Favorites { get; set; } 
    public IEnumerable<Notification> Notifications { get; set; } 
    public IEnumerable<Topic> SubscribedTopics { get; set; } 

    protected override void Validate() 
    { 
     if (string.IsNullOrWhiteSpace(Name)) 
     { 
      AddBrokenRule(new ValidationRule("Name", "Name_Missing")); 
     } 
     if (string.IsNullOrWhiteSpace(Email)) 
     { 
      AddBrokenRule(new ValidationRule("Email", "Email_Missing")); 
     } 
     if (string.IsNullOrWhiteSpace(Tag)) 
     { 
      AddBrokenRule(new ValidationRule("Tag", "Tag_Missing")); 
     } 
     System.Uri uriResult; 
     if (!string.IsNullOrWhiteSpace(Picture) && 
      Uri.TryCreate(Picture, UriKind.Absolute, out uriResult) && 
      (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps)) 
     { 
      AddBrokenRule(new ValidationRule("Picture", "Picture_InvalidURI")); 
     } 
    } 
} 

EntityBase將標識參數,所以就參數而言,這兩個類應該是相同的。

我遇到麻煩的部分是將數據實體映射到域實體。

public override IEnumerable<User> GetAll() 
    { 
     IEnumerable<User> user = _context.Users.Project() 
         .To<User>("Followers"); 
     return user; 
    } 

我認爲導致麻煩的是圓形導航屬性。 User1可能有一個名爲User2的追隨者,同時在User2之後。

到目前爲止,我曾經嘗試都AutoMapperValueInjecter,但我還沒有與任何任何成功。

  • 我試着給所有導航屬性添加「虛擬」,啓用惰性和代理加載,但這會導致AutoMapper和ValueInjecter都失敗。 ValueInjecter由於已經打開的數據讀取器和AutoMapper,因爲類型不匹配。
  • 我試過顯式加載導航屬性,但只要我在用戶包含(「關注」),我得到一個計算器。
  • 試圖創建一個AutoMapperConfiguration,其中我指定maxDepth爲1會產生一個計算器,除非我將opt.ExplicitExpansion添加到每個導航屬性。
  • 如果我再嘗試明確擴大導航財產,我得到

類型「ShortStuff.Domain.Entities.User」出現在兩個結構 不相容初始化一個單一的LINQ to Entities查詢中。 A 類型可以在同一個查詢中的兩個地方進行初始化,但只有在 兩個地方都設置了相同的屬性並且這些屬性是 以相同的順序設置。

理想情況下,我想要一個解決方案,讓我明確地控制哪些導航屬性擴展而無需遞歸。

例如,我想這樣做:

_context.Users.Include("Followers").NoNavigation().AsEnumerable(); 

然後,我將能夠訪問用戶。關注者並擁有其他用戶的列表,並將其導航屬性設置爲空。

非常感謝!我的存儲庫/服務學習項目的

完整的源代碼可以在Github在https://github.com/Bio2hazard/ShortStuff/tree/master/ShortStuffApi

編輯發現: 我取得了一些進展。

我得到的東西通過關閉代理生成&延遲加載,然後使用ValueInjector像這樣的工作:

 IEnumerable<Data.Entities.User> userList = _context.Users.Include("Followers").Include("Favorites").Include("Messages").Include("Notifications").Include("SubscribedTopics"); 

     IEnumerable<User> users = userList.Select(u => new User 
     { 
      Id = u.Id, 
      Email = u.Email, 
      Picture = u.Picture, 
      Tag = u.Tag, 
      Name = u.Name, 
      Followers = u.Followers.Select(uu => new User().InjectFrom<SmartConventionInjection>(uu)).Cast<User>(), 
      Favorites = u.Favorites.Select(uf => new Message().InjectFrom<SmartConventionInjection>(uf)).Cast<Message>(), 
      Messages = u.Messages.Select(um => new Message().InjectFrom<SmartConventionInjection>(um)).Cast<Message>(), 
      Notifications = u.Notifications.Select(un => new Notification().InjectFrom<SmartConventionInjection>(un)).Cast<Notification>(), 
      SubscribedTopics = u.SubscribedTopics.Select(ut => new Topic().InjectFrom<SmartConventionInjection>(ut)).Cast<Topic>() 
     }); 

但是,這是一噸的代碼。我可能可以爲此創建一個工廠,但必須有一個更簡單的方法,對吧?

回答