Как выставить часть Entity как DataContract? - PullRequest
2 голосов
/ 25 февраля 2012

До сих пор при работе с WCF я всегда выставлял целиком либо сгенерированные EF сущности, либо POCO (изменяя шаблон T4 для включения DataContract и DataMember для POCO и свойств) как DataContract.

Теперь я столкнулся с ситуацией, когда не могу раскрыть все целиком, и мне нужно явно указать мой DataContract как подмножество сущностей.

Стоит сказать, что одна из моих сущностей похожа на приведенную ниже.:

enter image description here

И я хочу просто выставить Id, Name, CategoryId, Price.

Вставить / обновить остальные поля (ActiveFrom, InactiveDate, Supported) - это то, что будет решаться на основе БР, и клиент ничего не знает и не должен знать о них.

Я пробовал следующие подходы, но каждый изкажется, что они имеют проблемы / не работают:

  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 Продукта.

Теперь мой вопрос заключается в том, как лучше всего получить то, что я хочу сделать (выставив подмножествоиз сущностей как DataContract)?

Ответы [ 2 ]

4 голосов
/ 25 февраля 2012

Я бы выбрал вариант 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);
2 голосов
/ 25 февраля 2012

Прежде всего, вы должны никогда представлять всю сущность как контракт данных, так как это объект домена, а не объект передачи данных. Не только в этой конкретной ситуации. Никогда. Теперь вы создаете непонятное несоответствие между сущностями, у которых есть DTO, и теми, у кого их нет.

Возвращаясь к вопросу: С AutoMapper вроде бы все в порядке. Вам просто нужно определить 2 отображения. И, возможно, игнорировать () пропущенные свойства при сопоставлении с сущностью.

...