使用DTO和POCO对象时,处理导航属性的最佳做法是什么? [英] What is the best practice to deal with navigation properties when using DTO and POCO objects?

查看:167
本文介绍了使用DTO和POCO对象时,处理导航属性的最佳做法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图围绕域驱动开发。我想确保我有一个很好的基础和理解,所以如果在这里避免使用AutoMapper或类似的建议,这将是非常好的。我的架构目前涉及:






  • WCF服务负责持久化(使用实体框架)和服务器端验证。它将POCO转换为DTO,并将DTO转移给客户端。


  • 客户端接收DTO并将其转换为POCO。转换POCO和DTO的类在服务和客户端之间共享。


  • POCO的实现 IValidatableObject INotifyPropertyChanged ,并由服务器和客户端使用,但它们不用于数据传输。 DTO是仅仅是没有行为的财产袋。




(1)问题#1。 此架构适用于域驱动设计。

(2)问题#2。 POCO是否适合包含导航属性? POCO在DDD架构中包含导航属性对我来说真的感觉错了,因为我有一个导航属性可能是或不是序列化没有意义。对于我来说,有一个专门的DTO会更有意义。



例如,这是一个POCO / DTO看起来像我的架构。

  //强制POCO和DTO之间的一致性
public interface IExample
{
Int32 Id {get;组; }
String Name {get;组; }


// POCO
public class示例:IExample,INotifyPropertyChanged,IValidatableObject
{
private int id;
私有字符串名称;

public Int32 Id {
get {return this.id; }
set {
this.id = value;
OnPropertyChanged(Id);
}
}

public String Name {
get {return this.name; }
set {
this.name = value;
OnPropertyChanged(Name);
}
}

public ICollection< Example2> ChildExamples {
get {...}
set {...}
}

// INotifyPropertyChanged成员
// IValidatableObject成员
}

// DTO
public class ExampleInfo:IExample
{
public Int32 Id {get;组; }
public String Name {get;组; }
public ICollection< Example2Info> ChildExamples {get;组; }
}

看起来不对,因为你可能并不总是需要导航属性和空(空)对象(或集合)在面向对象架构中似乎是非常错误的。您还必须处理序列化和转换深层对象层次结构,这并不是微不足道的。对于专门的DTO来说,这样做更有意义,所以空导航属性的可能性不一定是可能的,也可能不需要序列化或填充。

  public class ComplexInfo 
{
public Example ExampleInfo {get;组; }
public ICollection< Example2Info> ChildExamples {get;组; }
}

这些情况在真实的企业DDD风格架构中处理如何其他建议可以在这里给出?

解决方案

我同意Jehof关于将DTO发送给您的客户,并保持域模型清洁在您的WCF下的服务器端。



关于导航属性,Eric Evans在域驱动设计中强调的一点是尊重不变式。所以,在上面的例子中,问自己,Id和Name是否真的要在对象的生命周期中改变,还是不变量?很多DDD风格的开发人员甚至不会在这些属性上放置一个setter。而是通过构造函数构建对象的不变状态。如果Name可以更改,那么您可能需要一个名为Rename(string newName)的方法,因为您可能想要将某种业务规则放在那里。



上面的图层中的一个红色标记是您在DAL中拥有整个对象模型。你所说的组件真的不是什么大问题,但我认为这是你从数据角度继续考虑应用程序的趋势。 DDD的要点是在逻辑和行为方面考虑您的对象模型,而不是数据和结构。我(和大多数其他DDD开发人员,我认为)认为数据访问层是返回聚合根的Repository类。存储库负责将您的水化poco /实体对象从DAL(存储库)返回到业务层(以上,例如上述示例中的应用程序/服务层类或WCF)。在使用EF的情况下,您可以将存储库打包到您的DataContext调用并返回实体对象。



我可以继续下去,因为你的问题确实是针对DDD的基本原理,其中有几个。我会推荐1)阅读埃里克·埃文斯的书域驱动设计。 2)请记住,DDD针对复杂的业务软件。如果您尝试将其应用于一个简单的CRUD应用程序,这个应用程序真的只是将UI表单和数据绑定到数据库表中,很难看到DDD方法的形成,因为它所处理的问题不在此。所以保持透视。


I'm trying to wrap my head around Domain Driven Development. I want to make sure I have a good foundation and understanding of it, so it would be great if recommendations to use AutoMapper or similar are avoided here. My architecture currently involves the following:

  • The WCF service is responsible for persistence (using Entity Framework) and server-side validation. It converts POCO's to DTO's, and DTO's are transferred to the client.

  • The Client, receives DTO's and converts them to POCO's. The class that converts POCO's and DTO's is shared between the service and the client.

  • The POCO's implement IValidatableObject and INotifyPropertyChanged and are used by both the server and the client, but they are not used for data transfer. The DTO's are, which are just property bags containing no behavior.

(1) Question #1. Is this architecture appropriate for a Domain Driven Design.
(2) Question #2. Is it appropriate for POCO's to contain navigation properties? It really feels wrong for POCO's to contain navigation properties in a DDD architecture to me, because it doesn't make sense to me to have a navigation property that may or may not be serialized. It would make more sense to me to have a specialized DTO.

For example, here is a POCO/DTO looks like in my architecture.

// Enforces consistency between a POCO and DTO
public interface IExample
{
    Int32 Id { get; set; }
    String Name { get; set; }
}

// POCO
public class Example : IExample, INotifyPropertyChanged, IValidatableObject
{
    private int id;
    private string name;

    public Int32 Id {
        get { return this.id; }
        set {
            this.id = value;
            OnPropertyChanged("Id");
        }
    }

    public String Name {
        get { return this.name; }
        set {
            this.name = value;
            OnPropertyChanged("Name ");
        }
    }

    public ICollection<Example2> ChildExamples {
        get { ... }
        set { ... }
    }

    // INotifyPropertyChanged Members
    // IValidatableObject Members
}

// DTO
public class ExampleInfo : IExample
{
    public Int32 Id { get; set; }
    public String Name { get; set; }
    public ICollection<Example2Info> ChildExamples { get; set; }
}

It doesn't seem right though, because you may not always need the navigation property, and having an empty (null) object (or collection) seems very wrong in an object-oriented architecture. You also have to deal with serializing and converting deep object hierarchies at times, which is not trivial. It would make more sense for a specialized DTO so there isn't a problem with the constant possibility of empty navigation properties that may or may not need serialized or populated.

public class ComplexInfo
{
    public Example ExampleInfo { get; set; }
    public ICollection<Example2Info> ChildExamples { get; set; }
}

How are these situations handled in real-world enterprise DDD style architectures and what other advice can be given here?

解决方案

I agree with Jehof about sending the DTO's to your client and keeping the domain model clean on the server side under your WCF.

With respect to navigation properties, one point Eric Evans emphasizes in Domain Driven Design is to respect invariants. So, in your example above ask yourself if Id and Name are really going to change in the lifetime of the object, or are they invariants? A lot of DDD-style developers would not even put a setter on those properties. Instead build the object's invariant state through a constructor. If Name can change, you probably want a method called Rename(string newName), because there's probably some kind of business rules you'd want to put there anyway.

A red flag in your layers above is that you have your whole object model in the DAL. What you call your assemblies really isn't a big deal but I think it points to your tendency to keep thinking of the application from a data perspective. The point of DDD is to think of your object model in terms of logic and behavior, not data and structure. I (and most other DDD developers, I think) think of the data access layer as Repository classes which return Aggregate Roots. The repositories are responsible for returning your hydrated poco/entity objects from the DAL(repository) to the business layer (and above, such as an application/service layer class or your WCF in your above example). In your case of using EF, you'd have the repositories wrap your DataContext calls and return the entity objects.

I could go on and on, because your question is really targeting the basic fundamentals of DDD, of which there are several. I would recommend 1) Read Eric Evans book, "Domain Driven Design". 2) Keep in mind that DDD targets complex business software. If you're trying to apply it to a simple CRUD application which really is just UI forms and data binding to DB tables, its hard to see a DDD approach take shape, because the problems it addresses just aren't there. So keep that in perspective.

这篇关于使用DTO和POCO对象时,处理导航属性的最佳做法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆