我有以下课程,我试图补充:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
其中使用以下类来实现我的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;
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试运行参数化查询,它将水合到一个Product对象:
using (connection)
{
connection.Open();
return connection.QueryFirst<Product>(ReadQuery, new { VendorId = sku.VendorId.VendorShortname, SkuValue = sku.SkuValue });
}
Run Code Online (Sandbox Code Playgroud)
它抛出以下异常,因为它不知道如何处理Sku构造函数中的类型:
System.InvalidOperationException:Domain.Model.Products.Product实现需要一个无参数的默认构造函数或一个匹配的签名(System.String VendorId,System.String SkuValue,System.String Name,System.String Description,System.UInt64 IsArchived). "
我研究了使用自定义,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"));
}
Run Code Online (Sandbox Code Playgroud)
我想我可以创建一个特定的构造函数,Product(string VendorShortname, string SkuValue, string Name, string Description, UInt64 IsArchived)但我宁愿(必须)在映射代码而不是在我的域模型中有这个问题.
经过一些伪代码,我能做的就是滚动我自己的ORM,但是想通过Dapper来做类似的事情.
这将等同于VendorShortname使用VendorId(string vendorShortname),并且Name,Description,isArchived用于公共Product(Sku sku, string name, string description, bool isArchived)...一些同样被做的MongoDB按我的答案贴在下面的链接,一个小巧精致的手工映射相当于将真棒MongoDB的复合键:InvalidOperationException异常:{}文件.不支持身份
Run Code Online (Sandbox Code Playgroud)public static IEnumerable<dynamic> Query ( this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true )
然后,您可以使用动态对象列表构建所需的模型。
因此,使用原始帖子中的示例,参数化查询将从...更改
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"));
}
Run Code Online (Sandbox Code Playgroud)
到...
var ReadQuery = "SELECT VendorShortname, SkuValue, Name, Description, IsArchived FROM Products WHERE VendorShortname=@VendorShortname AND SkuValue=@SkuValue";
using (connection) {
connection.Open();
return connection.Query(ReadQuery, new { VendorShortname = sku.VendorId.VendorShortname, SkuValue = sku.SkuValue })
.Select(row => new Product(
new Sku(new VendorId(row.VendorShortname), row.SkuValue),
row.Name,
row.Description,
row.IsArchived)
);
}
Run Code Online (Sandbox Code Playgroud)
这就是该框架的预期目的。只需确保使用的属性直接映射到查询返回的字段即可。
这可能看起来很密集,但考虑到目标对象构造函数的复杂性,这是一个可行的解决方案。
| 归档时间: |
|
| 查看次数: |
1482 次 |
| 最近记录: |