问题: 我正在尝试使用 PetaPoco 连接四个以上的表,以用五个 B 类型的成员填充 A 类型的对象(与此问题非常相似:https://stackoverflow.com/a/11275334/296296)。根据我的阅读,可以使用以下语法:
var result = db.Query<Investment>(new System.Type[] { typeof(Investment), typeof(Person), typeof(Person), typeof(Person), typeof(Person), typeof(Person) }, null, sql, null).FirstOrDefault();
sql在哪里:
SELECT Investment.*, p1.*, p2.*, p3.*, p4.*, p5.* FROM Investment
INNER JOIN People p1 ON Investment.OwnerID = p1.Id
INNER JOIN People p2 ON Investment.ITOwnerID = p2.Id
INNER JOIN People p3 ON Investment.InformationOwnerId = p3.Id
INNER JOIN People p4 ON Investment.MaintenanceLeaderId = p4.Id
INNER JOIN People p5 ON Investment.MaintenanceLeaderITId = p5.Id
WHERE (Investment.Id = @0)
但它只是给了我以下错误:
无法自动加入人员,因为投资具有多个人员类型的财产
有谁遇到同样的问题或可以以任何方式提供帮助吗?
背景:
我有以下(简化的)数据库表:
Investment
--------------
Id
Name
OwnerId
ITOwnerId
InformationOwnerId
MaintenanceLeaderId
MaintenanceLeaderITId
People
--------------
Id
Name
我想要将这些数据库表映射到的类是:
Public class Investment {
public int Id
public string Name
public Person Owner
public Person ITOwner
public Person InformationOwner
public Person MaintenanceLeader
public Person MaintenanceLeaderIT
}
Public class Person {
public int Id
public string Name
}
为此,我需要加入 Investment 类中每个人员类型的 People 表,并将它们作为 Person 类型的实例映射到相应的属性。
您可能执行此操作的唯一方法是创建自己的回调(而不是让它回退到当前正在调用的自我发现回调),在其中连接 Investment 对象上的每个 Person 对象。
为什么你不能这样做:
/////用于测试选择的 SQL 代码
DECLARE @People TABLE (Id INT, Name VARCHAR(50))
INSERT INTO @People (Id,Name)
SELECT 1,' John Smith' UNION ALL
SELECT 2,'Albert Lee' UNION ALL
SELECT 3,'Christina Wetherbe' UNION ALL
SELECT 4,'Alice Cany' UNION ALL
SELECT 5,'Jim Blabery' UNION ALL
SELECT 6,'Octaviose Mayflower' UNION ALL
SELECT 7,'Sandra Lee M' UNION ALL
SELECT 8,'Some test user' UNION ALL
SELECT 9,'Some test user 2' UNION ALL
SELECT 10,'Some test user 3' UNION ALL
SELECT 11,'Some test user 4'
DECLARE @Investment TABLE (
Id INT,
Name VARCHAR(50),
OwnerId INT,
ITOwnerId INT,
InformationOwnerId INT,
MaintenanceLeaderId INT,
MaintenanceLeaderITId INT
)
INSERT INTO @Investment(Id,Name,OwnerId,ITOwnerId,InformationOwnerId,MaintenanceLeaderId,MaintenanceLeaderITId)
SELECT 1,'INVESTMENT 1',1,2,1,3,4 UNION ALL
SELECT 2,'INVESTMENT 2',1,3,2,3,2 UNION ALL
SELECT 3,'INVESTMENT 3',3,1,3,3,4 UNION ALL
SELECT 4,'INVESTMENT 4',5,4,4,2,3 UNION ALL
SELECT 5,'INVESTMENT 5',6,5,5,7,6 UNION ALL
SELECT 6,'INVESTMENT 6',8,6,6,7,8 UNION ALL
SELECT 7,'INVESTMENT 7',9,8,7,4,5 UNION ALL
SELECT 8,'INVESTMENT 8',11,8,8,6,11 UNION ALL
SELECT 9,'INVESTMENT 9',10,9,9,10,9
--SELECT * FROM @People
--SELECT * FROM @Investment
-- THIS IS YOUR SELECT STATEMENT to be uses in PetaPoco call
SELECT unpv.Id,unpv.Name, unpv.INVTYPE,unpv.PersonId,p.Name FROM @Investment
UNPIVOT(PersonId for INVTYPE in (OwnerId,ITOwnerId,InformationOwnerId,MaintenanceLeaderId,MaintenanceLeaderITId))unpv
join @People p on unpv.PersonId = p.Id
order by INVTYPE, PersonId
然后 C# 代码为
1 - 扩展您的投资 POCO 以增加 2 个列:INVTYPE 和 PersonId。只需在同一名称空间中创建新对象即可。像这样:
public partial class Investment
{
[ResultColumn]
public string INVTYPE { set; get; }
[ResultColumn]
public int PersonId { set; get; }
}
2 - 创建视图类 InvestmentView (您可以使用您的 Investment 类,只需重命名即可)
var myInvestmentView = new InvestmentView
{
Id = result.Id,
Name = result.Name,
Owner = new Person{ Id = result.firstOrDefault(o => o.INVTYPE.Equals("OwnerId")).PersonId, Name = result.firstOrDefault(o=> o.INVTYPE.Equals("OwnerId")).PersonName},
ITOwner = new Person{ Id = result.firstOrDefault(o => o.INVTYPE.Equals("ITOwnerId")).PersonId, Name = result.firstOrDefault(o=> o.INVTYPE.Equals("ITOwnerId")).PersonName},
InformationOwner = new Person{ Id = result.firstOrDefault(o => o.INVTYPE.Equals("InformationOwnerId")).PersonId, Name = result.firstOrDefault(o=> o.INVTYPE.Equals("InformationOwnerId")).PersonName},
MaintenanceLeader = new Person{ Id = result.firstOrDefault(o => o.INVTYPE.Equals("MaintenanceLeaderId")).PersonId, Name = result.firstOrDefault(o=> o.INVTYPE.Equals("MaintenanceLeaderId")).PersonName},
MaintenanceLeaderIT = new Person{ Id = result.firstOrDefault(o => o.INVTYPE.Equals("MaintenanceLeaderITId")).PersonId, Name = result.firstOrDefault(o=> o.INVTYPE.Equals("MaintenanceLeaderITId")).PersonName}
}
3 - 使用返回列表中的数据填充类
using (var data = new Database(Config.MainDbConnectionName))
{
var result = data.Fetch<Investment,People>(
Sql.Builder
.Append("SELECT unpv.Id,unpv.Name, unpv.INVTYPE,unpv.PersonId,p.name as PersonName FROM Investment")
.Append(" UNPIVOT(PersonId for INVTYPE in (OwnerId,ITOwnerId,InformationOwnerId,MaintenanceLeaderId,MaintenanceLeaderITId)) unpv")
.Append(" JOIN People p on unpv.PersonId = p.Id")
.Append(" WHERE (Investment.Id = @0)",InvId)
.Append(" ORDER BY INVTYPE, PersonId")
);
}
这样,唯一需要特殊处理的类将是 Investment 类,因为您需要将数据从 InvestmentView 向后处理为 POCO 的平面结构。