如何将实体的一部分公开为DataContract?

CjC*_*oax 3 c# wcf entity-framework datacontract automapper

到现在为止,在使用WCF时,我一直将整个EF生成的实体或POCO(通过修改T4模板以包含POCO和属性上的DataContract和DataMember)公开为DataContract。

现在,我遇到了一种情况,我无法公开全部内容,需要显式指定DataContract作为实体的子集。

值得一提的是,我的实体之一如下所示:

在此处输入图片说明

我只想公开ID,名称,CategoryId,价格。

字段的其余部分的插入/更新(ActiveFromInactiveDateSupported)的东西,将根据BR来决定,而客户不知道,也不应该确实知道,他们什么。

我尝试了以下方法,但是每种方法似乎都存在问题/不起作用:

  1. 使用AutoMapper:我需要将源对象映射到目标对象,这是一种单向映射,因此出于演示目的,我可以映射ProductProductContract。但是对于添加/更新产品,它无法工作,因为它无法进行双向映射

  2. 使用反射并为实体创建一个元数据类,然后将该[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; }
        }
    
    Run Code Online (Sandbox Code Playgroud)

    然后将ProductMD用作Product 部分类的属性,而无需触碰自动生成的实体(仅供参考:我已将POCO T4模板生成器更改为[DataContract]在每个实体上都包含 ):

    [MetadataType(typeof(ProductMD))]
    public partial class Product
    {  
    }
    
    Run Code Online (Sandbox Code Playgroud)

    但是在客户端,我无权访问任何DataMembers产品。

现在我的问题是,获得我想要做的事情的最佳方法是什么(将实体的子集公开为DataContract)?

Dar*_*rov 5

我会选择选项1-> AutoMapper。

它无法工作,因为它无法进行双向映射。

您可以定义两种方式的映射:

Mapper.CreateMap<Product, ProductContract>();
Mapper.CreateMap<ProductContract, Product>();
Run Code Online (Sandbox Code Playgroud)

显然,如果在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);
Run Code Online (Sandbox Code Playgroud)