C# 如何从存储库中检索域对象

C# 如何从存储库中检索域对象,c#,domain-driven-design,automapper,repository-pattern,ddd-repositories,C#,Domain Driven Design,Automapper,Repository Pattern,Ddd Repositories,我在理解存储库域对象关系方面有点问题。以下是我所知道的关于域设计的一些信息(它们也可能是错误的或不准确的)。考虑到这些,我无法找到从存储库获取域对象的方法 在DDD中,域应该知道并只包含业务所需的内容,其他所有内容都必须从域中清除。那很好。此外,从任何业务中抽象数据访问也是一种很好的做法。应用程序不需要知道我们在哪里存储数据或如何存储数据。我们只要求存储库给我们一个域对象,它给了我们想要的对象,或者另一种方式也是有效的,我们给存储库一个域对象,它将其发送到存储 声明域对象的公共setter在面向

我在理解存储库域对象关系方面有点问题。以下是我所知道的关于域设计的一些信息(它们也可能是错误的或不准确的)。考虑到这些,我无法找到从存储库获取域对象的方法

在DDD中,域应该知道并只包含业务所需的内容,其他所有内容都必须从域中清除。那很好。此外,从任何业务中抽象数据访问也是一种很好的做法。应用程序不需要知道我们在哪里存储数据或如何存储数据。我们只要求存储库给我们一个域对象,它给了我们想要的对象,或者另一种方式也是有效的,我们给存储库一个域对象,它将其发送到存储

声明域对象的公共setter在面向对象设计中也是一种非常糟糕的方法,因为我们无法控制谁在访问什么和更改什么。因此,只暴露对象外部所需的内容是一种很好的做法

因此,在我的脑海中,我无法找到实现我的存储库的方法。我可以在代码中使用任何ORM或纯sql来检索数据

但是我不能从持久性对象创建域对象

  • 因为它们没有公共设置器,所以我无法创建和设置字段值
  • 声明包含所有字段的公共构造函数似乎不正确。我可能需要填写几个模型,这意味着我必须用不同的参数集定义几个构造函数

  • 任何帮助都将不胜感激……

    我正试图理解您的疑问。关于如何进行的一些提示。 首先,域应该知道存储库契约,而不是实际的存储库基础结构。换句话说,您可以选择有3个类库,如下所示

  • XYZDomain(将了解XYZRepository并致电适当的 此接口的方法)
  • XYZRepository(包含接口IXYZService接口)
  • XYZSQLRepository(XYZRepository接口的实际实现)
  • 现在,您可以选择在何处使用依赖项注入将XYZSQLRepository注入XYZDomain

    如果需要,还可以尝试使用事件模型注册这些存储库


    使用自定义服务定位器获取具体对象

    如果ORM没有公共setter,则不能创建域对象。若您使用的是实体框架,那个么它肯定可以在模型优先的方法中映射私有属性,而在代码优先的方法中,您只需要publicgetter。我不知道其他ORM-s的情况如何。

    您可以选择:

    1。ORM可以处理私有字段。

    据我所知,ORMs(例如)可以通过非公共setter设置属性

    对于实体框架-,有一个例子证明了这一点

    如果使用NHibernate,您的设置器应为
    公共/受保护的虚拟
    /
    受保护的内部虚拟
    私有
    支持字段。你可以在SO问题中找到更多信息

    2。可以使用。

    它还可用于访问专用字段/属性

    3。让公共构造函数构造实体并不是一种坏做法。

    声明包含所有字段的公共构造函数似乎不正确。我可能需要填写几个模型,这意味着我必须用不同的参数集定义几个构造函数

    您的域实体只需要一个公共构造函数,其中包含它们所拥有的全部属性列表。尽管需要填写多个模型,但只有一个构造函数就足够了。存储库负责调用构造函数并将模型正确映射到其参数中

    编辑:

    4。可以使用。

    下面的测试显示,可以通过私有setter映射属性

    [TestClass]
    public class AutomapperTest
    {
        [TestMethod]
        public void Test()
        {
            // arrange
            Mapper.CreateMap<AModel, A>();
            var model = new AModel { Value = 100 };
    
            //act
            var entity = Mapper.Map<A>(model);
    
            // assert
            entity.Value.Should().Be(100);
            entity.Value.Should().Be(model.Value);
        }
    }
    
    public class AModel
    {
        public int Value { get; set; }
    }
    
    public class A
    {
        public int Value { get; private set; }
    } 
    
    [TestClass]
    公共类自动测试
    {
    [测试方法]
    公开无效测试()
    {
    //安排
    CreateMap();
    var模型=新AModel{Value=100};
    //表演
    var entity=Mapper.Map(模型);
    //断言
    entity.Value.Should()为(100);
    entity.Value.Should().Be(model.Value);
    }
    }
    公共类模型
    {
    公共int值{get;set;}
    }
    公共A类
    {
    公共int值{get;private set;}
    } 
    
    首先,感谢您的评论。但在这里,我对组件的解耦细节不感兴趣。我只是在想,我如何才能获得一个不公开任何字段的对象,并期望它从存储库中加载。我希望您同意业务逻辑或您的域,换句话说,应该与基础设施无关。如果我理解正确的话,您正在尝试创建一个可以反弹域对象的存储库,而不是反过来。我的观点是,业务不需要在infra中进行更改(例如,将ORM更改为其他内容)。存储库的职责是使用域类的公共方法设置域。所以,如果您正在寻找如何设置值,那么它将使用域方法。希望你明白为什么是方法而不是设定者谢谢你的提示。但我读过一篇文章,其中提到域模型和持久性模型是两个不同的集合,我认为这是正确的。在我当前的项目中,有一个非常糟糕的db-first设计,这对域逻辑来说是一场彻底的灾难。这就是我不想使用EF实体的原因。因此,我需要一个单独的域类集,以更好的方式表达所需的域。我的问题是,;如何将数据从EF实体获取到不公开公共属性的域对象?您的存储库(特定的数据映射器)可以负责将EF实体映射到域实体。我同意在or中使用单个公共构造函数