【发布时间】:2017-08-12 20:25:46
【问题描述】:
我有以下课程,我正在尝试补水:
public class Product
{
public readonly Sku Sku;
public string Name { get; private set; }
public string Description { get; private set; }
public bool IsArchived { get; private set; }
public Product(Sku sku, string name, string description, bool isArchived)
{
Sku = sku;
Name = name;
Description = description;
IsArchived = isArchived;
}
}
它使用以下类来实现我的 DDD 实体域模型中的概念(删除不相关的代码以保持代码简短,设置为只读以使构造后不可变):
public class Sku
{
public readonly VendorId VendorId;
public readonly string SkuValue;
public Sku(VendorId vendorId, string skuValue)
{
VendorId = vendorId;
SkuValue = skuValue;
}
}
public class VendorId
{
public readonly string VendorShortname;
public VendorId(string vendorShortname)
{
VendorShortname = vendorShortname;
}
}
我尝试运行参数化查询,它将水合到 Product 对象中:
using (connection)
{
connection.Open();
return connection.QueryFirst<Product>(ReadQuery, new { VendorId = sku.VendorId.VendorShortname, SkuValue = sku.SkuValue });
}
它不知道如何处理构造函数中的Sku类型,因此抛出以下异常:
System.InvalidOperationException: '一个无参数的默认构造函数 或一个匹配的签名(System.String VendorId、System.String SkuValue、System.String 名称、System.String 描述、System.UInt64 IsArchived) 是 Domain.Model.Products.Product 所必需的 物化'
我研究过使用自定义的SqlMapper.TypeHandler<Product>,但Parse(object value) 只从VendorId 数据库列中传入一个解析值(如果它在此处传入一个值数组,我可以自己进行映射)。
有没有办法自定义对象的处理,以便我可以将所有参数传递给构造函数,如下所示:
using (connection)
{
var command = connection.CreateCommand();
command.CommandText = "SELECT VendorShortname, SkuValue, Name, Description, IsArchived FROM Products WHERE VendorShortname=@VendorShortname AND SkuValue=@SkuValue";
command.Parameters.AddWithValue("@VendorShortname", sku.VendorId.VendorShortname);
command.Parameters.AddWithValue("@SkuValue", sku.SkuValue);
connection.Open();
var reader = command.ExecuteReader();
if (reader.HasRows==false)
return null;
reader.Read();
return new Product(
new Sku(new VendorId(reader.GetString("VendorId")),reader.GetString("SkuValue")),
reader.GetString("Name"),
reader.GetString("Description"),
reader.GetBoolean("IsArchived"));
}
我想我可以使用Product(string VendorShortname, string SkuValue, string Name, string Description, UInt64 IsArchived) 创建一个特定的构造函数,但我宁愿(必须)在映射代码中而不是在我的域模型中关注这个问题。
查看一些伪代码,我可以做的是推出自己的 ORM,但希望通过 Dapper 做类似的事情。
- 通过反射获取对象的所有构造函数
- 如果构造函数中的任何参数是类型,则获取其构造函数
- 对于每个构造函数(包括参数),将构造函数名称映射到 SQL 阅读器列(和类型)
这相当于VendorShortname 用于VendorId(string vendorShortname),Name、Description、isArchived 用于公共Product(Sku sku, string name, string description, bool isArchived)...根据我在以下链接,Dapper 手动映射等价物会很棒MongoDB Composite Key: InvalidOperationException: {document}.Identity is not supported
【问题讨论】:
-
but i would rather (must) have this concern in the mapping code rather than in my domain model.你能告诉我们为什么你必须这样吗? -
对于其他存储库 (MongoDB),我的域模型中没有任何持久性问题,我希望尽可能使用 SQL/Dapper,因为它使事情变得更简单。将更新我的帖子,了解需要做什么,可以自己动手,但不想重新发明轮子,也不能像 Dapper 那样编写代码