我遇到的问题是,我目前正在尝试获取具有多重映射的对象列表。我想要获取对象 A 的列表,其中包含对象 B,并且两者都单独保存在我的数据库中。以下是我的对象和表格。
对象是:
// Object A
public class TestObject
{
public int objectId { get; set; }
public string name { get; set; }
public ObjectDetail detailId { get; set; }
}
和
// Object B
public class ObjectDetail
{
public int detailId { get; set; }
public string owner { get; set; }
public string description { get; set; }
}
我的表是 dbo.testobject,其中包含“objectId”(主键 int)、“name”(nvarchar)、“detailId”(int)列;和 dbo.objectdetail ,其中包含“detailId”(主键 int)、“所有者”(nvarchar)、“描述”(nvarchar)列。
首先,我可以毫无问题地向表中插入行、匹配键以及查询 TestObject 的单个对象,能够调出所有详细信息,包括匹配的 ObjectDetail 中的详细信息。
但是,我一直在尝试获取 TestObject 列表。
我最初所做的是下面的代码。
string sql = $"select ob.*, de.* " +
$"from dbo.testobject ob " +
$"left join dbo.objectdetail de " +
$"on ob.detailId = de.detailId ";
using (IDbConnection connection)
{
var selected = connection.Query<TestObject, ObjectDetail, TestObject>(sql,
(test, detail) => { test.detailId = detail; return test; },
splitOn: "detailId");
}
这会返回错误:
System.Data.DataException:“解析第 2 列时出错(detailId=8 - Int32)”
InvalidCastException:从“System.Int32”到“SQLDataAccessDemo.ObjectDetail”的转换无效。and an Inner Exception of
所以我猜测可能是因为 dbo.testobject 中的“detailId”列与 TestObject 类中的detailId 的数据类型不匹配。所以然后我回去并修改了下面的代码。
// I first made changes to the classes
// TestObject is now int Id, string name, ObjectDetail detail
// ObjectDetail object is now int Id, string owner, string description
string sql = $"select ob.*, de.* " +
$"from dbo.testobject ob " +
$"left join dbo.objectdetail de " +
$"on ob.detailId = de.Id ";
using (IDbConnection connection)
{
var selected = connection.Query<TestObject, ObjectDetail, TestObject>(sql,
(test, detail) => { test.detail = detail; return test; });
}
哪个有效并且不会给出错误。
所以我的问题是,如何使其工作而不必更改我的初始表?
建议您不要使用后缀
Id
来命名对象属性。因此,您的 TestObject
类应该包含一个新属性: ObjectDetail
,它保存对象值。
请使用 Pascal 大小写来命名属性,如下 C# 命名约定。
public class TestObject
{
public int ObjectId { get; set; }
public string Name { get; set; }
public int DetailId { get; set; }
public ObjectDetail ObjectDetail { get; set; }
}
public class ObjectDetail
{
public int Id { get; set; }
public string Owner { get; set; }
public string Description { get; set; }
}
splitOn
:
string sql = $"select ob.*, de.* " +
$"from dbo.testobject ob " +
$"left join dbo.objectdetail de " +
$"on ob.detailId = de.Id ";
using (IDbConnection connection)
{
var selected = connection.Query<TestObject, ObjectDetail, TestObject>(sql,
(test, detail) =>
{
test.ObjectDetail = detail;
return test;
},
splitOn: "detailId");
}