多次映射到同一个表两次

时间:2018-06-11 16:07:00

标签: dapper

如何使用同一个表在两个字段上使用Dapper的多映射功能?即ClientInfo有两个Address个对象。

public class ClientInfo
{
    public Guid Id => Guid.NewGuid();
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Address PostalAddress { get; set; }
    public Address BillingAddress { get; set; } 
    public int ContactNumber { get; set; }        
}

public class Address
{
    public Guid Id = Guid.NewGuid();
    public string FirstLine { get; set; }
    public string SecondLine { get; set; }
    public string Town { get; set; }
    public string PostCode { get; set; }
}

Relational - 在ClientInfo.PostalAddress / BillingAddress

中使用的Address.Id
tbl.Address
|Id|FirstLine|SecondLine|Town|PostCode    

tbl.ClientInfo
|Id|FirstName|LastName|PostalAddress|BillingAddress|etc..

当前实施

仅在 PostalAddress 映射的所有内容中获得结果。

var sql = @"select * from ClientInfo c left join Address as a on a.Id = c.PostalAddress left join Address as ad on ad.Id = c.BillingAddress";

var clients = connection.Query<ClientInfo, Address, Address, ClientInfo>(
                    sql,
                    (client, postal, billing) =>
                    {
                        client.PostalAddress = postal;
                        client.BillingAddress = billing;
                        return client;
                    },
                    splitOn: "PostalAddress,BillingAddress")
                .Distinct()
                .ToList();

return clients;

2 个答案:

答案 0 :(得分:-1)

您当然不必在select语句中提供GUID,这只是让测试工作。

[Test]
public void TestAbcd()
{
    using (var dbConnection = new SqlConnection(_connectionString))
    {
        const string sql = @"WITH ClientInfo AS (

                                 SELECT * FROM (
                                     VALUES (@ci1, @adr1, @adr2), (@ci1, @adr3, @adr4)
                                     ) AS a (Id, PostalAddress, BillingAddress)
                             ),

                             Address AS (

                                 SELECT * FROM (
                                     VALUES
                                         (@adr1), (@adr2), (@adr3), (@adr4)
                                     ) AS a (Id)

                             )

                             select * from ClientInfo c left join Address as a on a.Id = c.PostalAddress left join Address as ad on ad.Id = c.BillingAddress";

        dbConnection.Open();

        var clients = dbConnection.Query<ClientInfo, Address, Address, ClientInfo>(
                sql,
                (client, postal, billing) =>
                {
                    client.PostalAddress = postal;
                    client.BillingAddress = billing;
                    return client;
                },
                splitOn: "PostalAddress,BillingAddress",  param: new {
                    ci1 = Guid.NewGuid(),
                    ci2 = Guid.NewGuid(),
                    adr1 = Guid.NewGuid(), 
                    adr2 = Guid.NewGuid(),
                    adr3 = Guid.NewGuid(),
                    adr4 = Guid.NewGuid()
                })
            .Distinct()
            .ToList();

    }
}

答案 1 :(得分:-1)

splitOn参数告诉Dapper何时/何处开始映射下一个对象,因此您需要确保SQL查询以正确的顺序返回信息。现在,您为PostalAddress和BillingAddress返回2个guid。 Dapper不知道如何映射它们。

select * from ... join ...将导致在AddressClientInfo.PostalAddress列之后订购ClientInfo.BillingAddress个数据。

尝试:SELECT c.Id, c.FirstName, c.LastName, c.ContactNumber, a.*, ad.* FROM ClientInfo c LEFT JOIN Address AS a ON a.Id = c.PostalAddress JOIN Address AS ad ON ad.Id = c.BillingAddress

如您所见,删除*实际上会从结果中排除PostalAddressBillingAddress guids,现在我们可以splitOn: "Id,Id"