简体   繁体   English

使用dapper和JOIN

[英]Using dapper with JOIN

I have a query with a number of joins like: 我有一个查询与许多连接,如:

var sqlFindByProviderNameAndProviderSubjectId = $@"
     SELECT u.*, la.*, p.*, cp.*, scr.*, lm.*, wm.*
     FROM [user].[User] u
     LEFT JOIN [user].[LinkedAccount] la ON u.Id = la.UserId
     LEFT JOIN [user].[PatientProfile] p ON u.Id = p.UserId
     LEFT JOIN [user].[CareProviderProfile] cp ON u.Id = cp.UserId                
     LEFT JOIN [user].[Screening] scr ON u.Id = scr.UserId
     LEFT JOIN [user].[LengthMeasurement] lm ON scr.Id = lm.ScreeningId
     LEFT JOIN [user].[WeightMeasurement] wm ON scr.Id = wm.ScreeningId                 
                WHERE u.Id = (
                    SELECT UserId
                    FROM [user].[LinkedAccount] la
                    WHERE la.ProviderName = @ProviderName AND la.ProviderSubjectId = @ProviderSubjectId)";

I use dapper to dematerialize the tables into strongly typed entities like: 我使用dapper将表非物质化为强类型实体,如:

await UnitOfWork.Connection.QueryAsync<User, LinkedAccount, PatientProfile, CareProviderProfile, Screening, LengthMeasurement, WeightMeasurement, User>(query,
    (u, la, p, cp, scr, lm, wm) =>
    {
        // mapping code here
    }

This works fine. 这很好用。

However, I have to add one additional JOIN to the query, but unfortunately the QueryAsync<> takes maximum 7 parameters/types, and I have more. 但是,我必须在查询中添加一个额外的JOIN,但遗憾的是QueryAsync <>最多需要7个参数/类型,而且我还有更多。

Is there another way to map multiple tables from a JOIN into entities? 是否有另一种方法将多个表从JOIN映射到实体?

Dapper does not care about your joins, what Dapper does care about is the tabular structure. Dapper并不关心你的连接,Dapper所关心的是表格结构。 The framework uses an id column by default, or a custom SplitOn to parse the tabular structure into an object. 框架默认使用id列,或者使用自定义SplitOn将表格结构解析为对象。 So a tabular structure in the following manner: 所以表格式结构如下:

Tabular:
Id | A | Id | B | Id | C | Id | D | Id | E | Id | F | Id | G | Id | H

You are telling Dapper that eight entities exists, Dapper does this by the id column. 你告诉Dapper存在八个实体,Dapper通过id列执行此操作。 Now, if you have an entity but it does not require to be abstracted in this manner, for instance A, B, and C should be in a single entity then you can tell Dapper to not create a separate entity for them by producing the following structure. 现在,如果您有一个实体但不需要以这种方式进行抽象,例如A,B和C应该在一个实体中,那么您可以通过生成以下内容告诉Dapper不为它们创建单独的实体结构体。

Tabular:
Id | A | B | C | Id | D | Id | E | Id | F | Id | G | Id | H

The point I am making is an entity should not represent a table, but an object that represents your intent. 我要点是一个实体不应该代表一个表,而是一个代表你意图的对象。 For instance a user may have address information, but in a database they'll likely be separate tables but in your application they may be one object. 例如,用户可能有地址信息,但在数据库中,他们可能是单独的表,但在您的应用程序中,它们可能是一个对象。

Based on the data tables I assume you can merge a couple without loosing business intent. 根据数据表,我假设您可以合并一对,而不会失去业务意图。 Which based on the split would resolve your issue, otherwise I am not sure how you would exceed the seven split functionality built into Dapper. 哪个基于拆分可以解决您的问题,否则我不确定您将如何超过Dapper内置的七个拆分功能。

So this is what I ended up doing. 所以这就是我最终做的事情。

My main query only retrieves user, linked accounts, and profile: 我的主查询仅检索用户,关联帐户和配置文件:

var sqlFindByProviderNameAndProviderSubjectId = $@"
            SELECT u.*, la.*, p.*, cp.*
            FROM [user].[User] u
            LEFT JOIN [user].[LinkedAccount] la ON u.Id = la.UserId
            LEFT JOIN [user].[PatientProfile] p ON u.Id = p.UserId
            LEFT JOIN [user].[CareProviderProfile] cp ON u.Id = cp.UserId                
            WHERE u.Id = (
                SELECT UserId
                FROM [user].[LinkedAccount] la
                WHERE la.ProviderName = @ProviderName AND la.ProviderSubjectId = @ProviderSubjectId)";

The application layer can specify a boolean IncludeScreening , and if true, I also do a second call to get the screening information: 应用程序层可以指定布尔值IncludeScreening ,如果为true,我还会进行第二次调用以获取筛选信息:

var sqlFindScreeningForUser = $@"
                SELECT scr.*, lm.*, wm.*, n.*
                FROM [user].[Screening] scr                
                LEFT JOIN [user].[LengthMeasurement] lm ON scr.Id = lm.ScreeningId
                LEFT JOIN [user].[WeightMeasurement] wm ON scr.Id = wm.ScreeningId
                LEFT JOIN [user].[Note] n ON scr.Id = n.ScreeningId
                WHERE scr.UserId = @UserId";

...and the resulting Screening is then set on the user. ...然后在用户上设置生成的Screening

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM