如何将部分Entity公开为DataContract?

时间:2012-02-25 04:46:29

标签: c# wcf entity-framework automapper datacontract

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

现在,我遇到了一种情况,我无法公开整个事情,需要明确指定我的DataContract作为实体的子集。

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

enter image description here

我想公开Id,Name,CategoryId,Price。

插入/更新其余字段(ActiveFromInactiveDateSupported)是基于BR决定的,客户端不知道,应该不知道,关于他们的一切。

我尝试了以下方法,但每个方法似乎都有问题/无效:

  1. 使用 AutoMapper :我需要将源对象映射到 目标对象,这是单向映射,所以对于 演示目的我可以将Product映射到ProductContract。但是,对于添加/更新产品,它确实如此 不能正常工作,因为它不能做双向映射

  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; }
        }
    

    然后使用ProductMD作为Product的属性 部分类没有触及自动生成的实体(仅供参考:我有 改变了POCO T4模板生成器以包含 每个实体[DataContract]

    [MetadataType(typeof(ProductMD))]
    public partial class Product
    {  
    }
    

    但在客户端,我没有 访问产品的任何DataMembers

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

2 个答案:

答案 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()。