Автоматическое отображение не работает

#c# #linq #entity-framework #many-to-many #automapper

#c# #linq #entity-framework #многие ко многим #automapper

Вопрос:

У меня есть 2 таблицы, в которых сохранены члены семейства, и приведенный ниже LINQ выполнен на 100% и вернул результат. Я пытался сопоставить с помощью Automapper, но это не работает, у customerViewItem нет данных и нет ошибки, не мог бы кто-нибудь посоветовать, заранее спасибо.

POCO

 public  class Cust_ProfileTbl
{
    [Key]
    public long bintAccountNo { get; set; } 
    public string nvarCardName { get; set; }
    public string varEmail { get; set; }


    public virtual ICollection<Cust_ProfileFamilyTbl> profileFamilyParents { get; set; }
    public virtual ICollection<Cust_ProfileFamilyTbl> profileFamilyChildren { get; set; }
}

public class Cust_ProfileFamilyTbl
{
    [Key]
    public int intProfileFamily { get; set; } 
    public long bintAccountNo { get; set; }
    public long bintAccountNoMember { get; set; }

    public virtual Cust_ProfileTbl custProfileParent { get; set; }
    public virtual Cust_ProfileTbl custProfileChild { get; set; }
}
  

В OnModelCreating

 modelBuilder.Entity<Cust_ProfileFamilyTbl>()
       .HasRequired(m => m.custProfileParent)
       .WithMany(t => t.profileFamilyParents)
       .HasForeignKey(m => m.bintAccountNo)
       .WillCascadeOnDelete(false);

modelBuilder.Entity<Cust_ProfileFamilyTbl>()
            .HasRequired(m => m.custProfileChild)
            .WithMany(t => t.profileFamilyChildren)
            .HasForeignKey(m => m.bintAccountNoMember)
            .WillCascadeOnDelete(false);
  

ViewModels

 public class Profile  
{

    public long bintAccountNo { get; set; }
    public string varCardNo { get; set; }
    public string nvarCardName { get; set; }

    public string varEmail { get; set; }

    public virtual ICollection<ProfileFamily> profileFamilyParents { get; set; }
    public virtual ICollection<ProfileFamily> profileFamilyChildren { get; set; }
    public Profile()
    {
        profileFamilyParents = new Collection<ProfileFamily>();
        profileFamilyChildren = new Collection<ProfileFamily>();
    }


}

public class ProfileFamily 
{
    public int intProfileFamily { get; set; }
    public long bintAccountNo { get; set; }
    public long bintAccountNoMember { get; set; }

   public Profile custProfileParent { get; set; }

}
  

LINQ и AutoMapper

 System.Linq.Expressions.Expression<Func<Cust_ProfileTbl, bool>> wherep = (x) => x.bintAccountNo.Equals(1);

Cust_ProfileTbl rs = (from family in context.member.Include("profileFamilyParents.custProfileChild")
                    .Where(wherep)
                      select family).Single();

Mapper.CreateMap<Cust_ProfileTbl, EFWeb.ViewModels.Profile>();

EFWeb.ViewModels.Profile customerViewItem = Mapper.Map<Cust_ProfileTbl, EFWeb.ViewModels.Profile>(rs);
  

Комментарии:

1. Не работает? Пожалуйста, уточните, в чем ошибка?

2. ошибки нет, просто у custmerViewItem нет данных после выполнения этого средства сопоставления строк. Создайте карту<Список<Cust_ProfileTbl>, список<EFWeb.ViewModels. Профиль>>(); Список<EFWeb.ViewModels.ViewModels. Профиль> customerViewItem = Mapper.Map<Список<Cust_ProfileTbl>, Список<EFWeb.ViewModels. Профиль>>(rs);

3. Где и как вы инициализируете свой CreateMap()?

4. Попробуйте изменить CreateMap на Mapper.CreateMap<Cust_ProfileTbl, EFWeb.ViewModels.Profile>(); . Automapper пока обрабатывает списки сам. Вам также потребуется внести те же изменения в параметры типа метода Map.

5. @DavidL, я перехожу к образцу по этой ссылке codeproject.com/Articles/61629/AutoMapper . и я думаю, вы имеете в виду эту строку -> Mapper. Создайте карту<Список<Cust_ProfileTbl>, список<EFWeb.ViewModels. Profile>>(); и это весь код, который у меня есть.

Ответ №1:

Во-первых, вам не следует создавать map для сопоставления a List<A> с a List<B> . Вы должны просто создать карту от A до B — automapper знает, как сопоставить List<A> с List<B> , если вы дадите ему карту от A до B . Это означает, что ваша карта должна быть:

 Mapper.CreateMap<Cust_ProfileTbl, EFWeb.ViewModels.Profile>();
  

Во-вторых, automapper не будет знать, как сопоставить ваши ICollection<Cust_ProfileFamilyTbl> свойства в вашей сущности со ICollection<ProfileFamily> свойствами в вашей viewmodel. Вам необходимо предоставить карту для этих типов:

 Mapper.CreateMap<Cust_ProfileFamilyTbl, EFWeb.ViewModels.ProfileFamily>();
  

Комментарии:

1. 1 для строки «Во-первых, вам не следует создавать map для сопоставления списка<A> со списком<B>».

Ответ №2:

Всегда рекомендуется инициализировать ваши карты внутри начальной точки входа приложения. В проекте MVC это было бы в global.asax, а в приложении WPF это был бы файл app.xaml.cs.

Если бы мы инициализировали в global.asax, это выглядело бы примерно так:

 protected void Application_Startup()
{
    Mapper.CreateMap<Cust_ProfileTbl, EFWeb.ViewModels.Profile>();
}
  

Обратите внимание, что мы не сопоставляем от типа к типу, не из списка типов в список типов, что означает, что нам нужно выполнять итеративное сопоставление.

 List<EFWeb.ViewModels.Profile> customerViewItem = rs.Select(x => Mapper.Map<Cust_ProfileTbl>(x)).ToList();
  

Теперь есть большая вероятность, что ваша карта все равно выйдет из строя, поскольку ваши свойства не совпадают с каждой стороны. Если это так, вам следует использовать .Методы расширения IgnoreMember() в вашей CreateMap игнорируют элементы, которые не могут быть сопоставлены, поскольку у них нет соответствующего типа приема.