#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 игнорируют элементы, которые не могут быть сопоставлены, поскольку у них нет соответствующего типа приема.