Automapper:如何忽略EF(VB.NET)中的导航属性
我是EF和AutoMapper的新手,我正试图用它来创建一个web服务。如果我尝试直接序列化EF实体,导航属性会抛出错误,因为它们无法序列化。我想找到一种抑制它们的方法,我被告知最好的方法是创建POCO用作数据传输对象 (在这一点上,我想我也可以使用ADO.NET编写自己的DTO——EF不应该为我省去编写自己的类的麻烦吗?) 我已经向我推荐了AutoMapper,作为将EF实体自动映射到POCO的一种方法,因此我尝试在以下过程中使用它,加载POCO:Automapper:如何忽略EF(VB.NET)中的导航属性,vb.net,entity-framework,automapper,Vb.net,Entity Framework,Automapper,我是EF和AutoMapper的新手,我正试图用它来创建一个web服务。如果我尝试直接序列化EF实体,导航属性会抛出错误,因为它们无法序列化。我想找到一种抑制它们的方法,我被告知最好的方法是创建POCO用作数据传输对象 (在这一点上,我想我也可以使用ADO.NET编写自己的DTO——EF不应该为我省去编写自己的类的麻烦吗?) 我已经向我推荐了AutoMapper,作为将EF实体自动映射到POCO的一种方法,因此我尝试在以下过程中使用它,加载POCO: Public Sub Load(ByVal
Public Sub Load(ByVal lngUserId As Long)
Dim query = From u In db.Users
Where u.UserID = lngUserId
Select u
AutoMapper.Mapper.Map(query.FirstOrDefault(), Me)
End Sub
问题是,它又出现了一个与导航属性相关的错误,AutoMapper似乎不会自动忽略该错误
因此,我尝试添加这一行以强制AutoMapper忽略nav属性:
Dim oMap = Mapper.CreateMap(Of User, UserDto).ForSourceMember(Sub(src) src.tblUserFarms, Sub(opt) opt.Ignore())
(tblUserFarms为资产净值财产)
我从我找到的一个C#示例中转换了语法,但似乎.ForSourceMember的第一个参数不应该是Lambda表达式,而且我找不到一个好的示例来说明如何使用它
我是在使用正确的方法,还是应该尝试其他方法?我是否应该简单地删除所有导航属性以解决问题,并失去它们的好处?EF是这项工作的合适工具吗?下面是我如何做的代码片段。在忽略的情况下,我避免了加载导航属性对象(也提高了性能)
public domain.Entities.UserProfile GetUserProfile(字符串用户名)
{
Mapper.CreateMap()
.FormMember(dest=>dest.BillingAddress,opt=>opt.Ignore())
.FormMember(dest=>dest.ShippingAddress,opt=>opt.Ignore())
.ForMember(dest=>dest.Orders,opt=>opt.Ignore())
.FormMember(dest=>dest.ShoppingCartItems,opt=>opt.Ignore());
Entities.UserProfile storedProfile=db.UserProfiles.FirstOrDefault(x=>x.UserName.Equals(UserName));
var profile=Mapper.Map(storedProfile);
回报曲线;
}
这就是我定义UserProfile的方式
public class UserProfile
{
public virtual int UserId { get; set; }
public virtual string UserName { get; set; }
public virtual string Prefix { get; set; }
public virtual string FirstName { get; set; }
public virtual string MiddleName { get; set; }
public virtual string LastName { get; set; }
public virtual string EmailAddress { get; set; }
public virtual string Company { get; set; }
public virtual string PhoneNumber { get; set; }
public virtual string FaxNumber { get; set; }
private ICollection<ShoppingCartItem> _shoppingCartItems;
private ICollection<Address> _addresses;
private ICollection<Order> _orders;
/// <summary>
/// Default billing address
/// </summary>
public virtual Address BillingAddress { get; set; }
/// <summary>
/// Default shipping address
/// </summary>
public virtual Address ShippingAddress { get; set; }
/// <summary>
/// Gets or sets customer addresses
/// </summary>
public virtual ICollection<Address> Addresses
{
get { return _addresses ?? (_addresses = new List<Address>()); }
protected set { _addresses = value; }
}
/// <summary>
/// Gets or sets orders
/// </summary>
public virtual ICollection<Order> Orders
{
get { return _orders ?? (_orders = new List<Order>()); }
protected set { _orders = value; }
}
/// <summary>
/// Gets or sets shopping cart items
/// </summary>
public virtual ICollection<ShoppingCartItem> ShoppingCartItems
{
get { return _shoppingCartItems ?? (_shoppingCartItems = new List<ShoppingCartItem>()); }
protected set { _shoppingCartItems = value; }
}
}
公共类用户配置文件
{
公共虚拟int用户标识{get;set;}
公共虚拟字符串用户名{get;set;}
公共虚拟字符串前缀{get;set;}
公共虚拟字符串FirstName{get;set;}
公共虚拟字符串MiddleName{get;set;}
公共虚拟字符串LastName{get;set;}
公共虚拟字符串EmailAddress{get;set;}
公共虚拟字符串公司{get;set;}
公共虚拟字符串PhoneNumber{get;set;}
公共虚拟字符串FaxNumber{get;set;}
私人ICollection_购物车项目;
专用ICollection\u地址;
私人ICollection_订单;
///
///默认帐单地址
///
公共虚拟地址计费地址{get;set;}
///
///默认送货地址
///
公共虚拟地址ShippingAddress{get;set;}
///
///获取或设置客户地址
///
公共虚拟ICollection地址
{
获取{返回_地址???(_地址=新列表());}
受保护集{u addresses=value;}
}
///
///获取或设置订单
///
公共虚拟ICollection订单
{
获取{return _orders???(_orders=new List());}
受保护集{u orders=value;}
}
///
///获取或设置购物车项目
///
公共虚拟ICollection ShoppingCartItems
{
获取{return _shoppingcartimes???(_shoppingcartimes=new List());}
受保护集{u shoppingCartItems=value;}
}
}
此时,我不得不继续我的项目,因此我选择编写自己的映射代码,将一些to/from映射方法放入DTO,将导航属性从ICollections转换为需要的列表。这不是最优雅的解决方案,但它能让我完全掌控局面。是的,我已经得出结论,EF实际上根本没有节省我任何编码时间,我仍然需要编写同样多的管道代码-唯一的区别是我编写的是LINQ查询而不是SQL,并且可以选择以后更改RDBMS。感谢Geovani,我一定会花些时间尝试一下。不幸的是,我的项目进展太远,无法从我现在使用的自定义代码更改回Automapper。
public class UserProfile
{
public virtual int UserId { get; set; }
public virtual string UserName { get; set; }
public virtual string Prefix { get; set; }
public virtual string FirstName { get; set; }
public virtual string MiddleName { get; set; }
public virtual string LastName { get; set; }
public virtual string EmailAddress { get; set; }
public virtual string Company { get; set; }
public virtual string PhoneNumber { get; set; }
public virtual string FaxNumber { get; set; }
private ICollection<ShoppingCartItem> _shoppingCartItems;
private ICollection<Address> _addresses;
private ICollection<Order> _orders;
/// <summary>
/// Default billing address
/// </summary>
public virtual Address BillingAddress { get; set; }
/// <summary>
/// Default shipping address
/// </summary>
public virtual Address ShippingAddress { get; set; }
/// <summary>
/// Gets or sets customer addresses
/// </summary>
public virtual ICollection<Address> Addresses
{
get { return _addresses ?? (_addresses = new List<Address>()); }
protected set { _addresses = value; }
}
/// <summary>
/// Gets or sets orders
/// </summary>
public virtual ICollection<Order> Orders
{
get { return _orders ?? (_orders = new List<Order>()); }
protected set { _orders = value; }
}
/// <summary>
/// Gets or sets shopping cart items
/// </summary>
public virtual ICollection<ShoppingCartItem> ShoppingCartItems
{
get { return _shoppingCartItems ?? (_shoppingCartItems = new List<ShoppingCartItem>()); }
protected set { _shoppingCartItems = value; }
}
}