.NET Dapper - 映射计算属性

Posted

技术标签:

【中文标题】.NET Dapper - 映射计算属性【英文标题】:.NET Dapper - Mapping computed properties 【发布时间】:2017-03-15 11:27:40 【问题描述】:

我正在使用 Dapper 处理 .NET 项目中的数据库连接。自动列映射效果很好,我还可以将列映射到模型中的不同属性名称。但是,如何映射计算属性?例如,我的模型是

class User

    public int Id get; set;
    public string Name get; set;
    public bool IsPremiumUser get; set;

桌子是

Id | Name | CreationDate | IsPremiumUser

现在,IsPremiumUser 在 db 中可以为 null,但在模型中则不能。我希望它被以下逻辑映射:

if (row.IsPremiumUser != null)

    model.IsPremiumUser = row.IsPremiumUser;

else

    model.IsPremiumUser = row.CreationDate < 1.1.2000;

换句话说,它的值取决于 2 列。还有多种情况我想根据是否存在某种关系来设置布尔属性。如何处理这些更复杂的映射情况?

【问题讨论】:

当您尝试将项目保存回数据库时,此映射应如何工作?如果IsPremiumUser 为空(当你读到它时),它应该被更新并有一个值吗? 也许你只需要额外的属性来计算但不会映射到数据库表? 是的,这正是我的意思。这些计算值不会保存回 db。 【参考方案1】:

只需使用 SQL 查询,它将检查 IsPremiumUser 字段是否不为空,如果用户没有设置此标志,则返回创建日期检查结果:

var sql =
    @"SELECT 
        Id,
        Name,
        CASE
            WHEN IsPremiumUser IS NOT NULL
                THEN IsPremiumUser
                ELSE CAST(CASE WHEN CreationDate < '2000-01-01' THEN 1 ELSE 0 END AS BIT)
        END AS IsPremiumUser
        FROM Users";
var users = conn.Query<User>(sql);

其他选项将使用动态查询并手动将结果映射到用户类:

var sql = @"SELECT Id, Name, CreationDate, IsPremiumUser FROM Users";
var millenium = new DateTime(2000, 1, 1);

var users = conn.Query(sql).Select(row => new User 
       Id = row.Id,
       Name = row.Name,
       IsPremiumUser = row.IsPremiumUser == null
           ? row.CreationDate < millenium
           : row.IsPremiumUser
    );

【讨论】:

谢谢,我最终使用了这种方法,尽管这并不是我的想法。如果我有一些更复杂的映射逻辑不方便在 db 端做呢? @eko 请刷新页面 :) 请记住,Dapper 会将 IsPremiumUser 标志返回为 null 或布尔值。它不会返回可为空的布尔值【参考方案2】:

另一种选择是建立一个工厂,让它组装用户:

var userRecords = _connection.Query<UserRecord>("select * from users");   
var users = UserFactory.Build(userRecords);
UserRecord 类仅用于查询数据 工厂将处理属性映射和动态属性

优点:保持 SQL 查询没有逻辑。随着时间的推移,工厂变得更加灵活。

缺点:更多代码

【讨论】:

以上是关于.NET Dapper - 映射计算属性的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法使用 Dapper 将列名映射到我的实体的属性?

为啥我从 Dapper 返回的对象具有 null 和默认属性值?

.NET Dapper 可为空的强制转换错误

使用 Dapper 映射 Uri 字段

如何使用 JPA 和 Hibernate 映射计算的属性

在 Nhibernate QueryOver 中使用计算属性(未映射)