到目前为止,在使用WCF时,我一直在暴露整个EF生成的实体或POCO(通过修改T4模板以在POCO和属性上包含DataContract和DataMember)作为DataContract。
现在,我遇到了一种情况,我无法公开整个事情,需要明确指定我的DataContract作为实体的子集。
值得一提的是,我的一个实体如下所示:
我想公开Id,Name,CategoryId,Price。
插入/更新其余字段(ActiveFrom
,InactiveDate
,Supported
)是基于BR决定的,客户端不知道,应该不知道,关于他们的一切。
我尝试了以下方法,但每个方法似乎都有问题/无效:
使用 AutoMapper :我需要将源对象映射到
目标对象,这是单向映射,所以对于
演示目的我可以将Product
映射到ProductContract
。但是,对于添加/更新产品,它确实如此
不能正常工作,因为它不能做双向映射。
使用反射并为实体创建元数据类
将[DataMember]
属性添加到Metadata类的属性,如下所示
(请注意,我没有包含不需要的字段):
public class ProductMD : AssociatedMetadataTypeTypeDescriptionProvider
{
public ProductMD() :
base(typeof(Product))
{
}
[DataMember]
public int Id{ get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public int? CategoryID { get; set; }
[DataMember]
public decimal? Price { get; set; }
}
然后使用ProductMD
作为Product
的属性
部分类没有触及自动生成的实体(仅供参考:我有
改变了POCO T4模板生成器以包含
每个实体[DataContract]
:
[MetadataType(typeof(ProductMD))]
public partial class Product
{
}
但在客户端,我没有
访问产品的任何DataMembers
。
现在我的问题是,获得我想要做的事情的最佳方法是什么(将实体的子集暴露为DataContract
)?
答案 0 :(得分:4)
我会选择选项1 - > AutoMapper。
它不起作用,因为它无法进行双向映射。
您可以定义双向映射:
Mapper.CreateMap<Product, ProductContract>();
Mapper.CreateMap<ProductContract, Product>();
很明显,如果在您的ProductContract
中,在进行映射时,您的属性少于域模型中的属性,则只会填充相应的属性。
在执行逆映射以进行更新时,您可以执行以下操作:
ProductContract pc = ...
Product productToUpdate = GetProduct(pc.Id);
Mapper.Map<ProductContract, Product>(pc, product);
// at this stage the product model will have the properties that
// were present in the ProductContract being mapped from them and
// the rest of the properties will stay unmodified, i.e. they will
// have their initial values that were retrieved from the database.
// Now we can update the product:
UpdateProduct(product);
答案 1 :(得分:2)
首先,您应该从不将整个实体公开为数据协定,因为它是域对象,而不是数据传输对象。不只是在那种特殊情况下。决不。现在,您在具有DTO的实体与不具有DTO的实体之间创建了令人困惑的不一致。
回到问题: AutoMapper似乎还不错。您只需定义2个映射。映射回实体时可能忽略属性Ignore()。