ServiceStack ORMLite和Dapper协同工作的问题

时间:2013-01-31 15:44:41

标签: c# dapper ormlite-servicestack

这是我第三天使用ServiceStack ORMLite进行实验。我的示例项目过去只与Dapper一起工作,现在它是Dapper和ServiceStack ORMLite的混合体,充分利用了两者的优势。

昨晚我正在努力解决Dapper问题。它基本上是一个选择连接4个表,它们在ORMLite的代码进入之前运行正常。现在它反复针对对象的表映射失败。它不会破坏它只是为对象分配错误的值。

我不得不继续前进,因为我所做的是使用Dapper的QueryMultiple执行4个选择中的每一个而不使用SQL连接,然后在C#上逐个加入结果。

请不要开始大笑。我知道这当然不是最好的解决方案。然而它仍然是一次访问数据库,但它并不自然。当行数增加时,这很可能是性能问题。

今天早上我想我发现了我的问题的根源:我正在使用ORMLite删除并创建表,并注意到字段顺序并不像我预期的那样。在ORMLite代码之前我只是手动运行SQL脚本,所以我决定了字段的顺序。由于我的项目需要支持最终用户所需的MySql,Postgresql和SQL Server,因此保持同步这些脚本的三个版本将是一件痛苦的事。我想用ORMLite自动化这个过程,当然可以利用它。

现在让我解释一下我的理论,你们专家可以决定我是对还是错。使用连接的Dapper查询根据命名约定将每个表的结果拆分为映射到每个类。它希望“Id”或“id”字段成为表格中的第一个字段。

我知道Dapper有一个“SplitOn”选项来处理不遵循其命名约定的表(“IdProduct”作为PK而不是“Id”)但在我的情况下它不能像那样使用,因为我真的没有对ORMLite的 CreateTable 函数中字段的排序方式的任何控制。最终可能会出现“id”,因此导致我现在遇到同样的问题。

也许查看我的代码可以给你更多线索。这是在ORMLite之前正常工作的代码:

        using (var conn = this.ConnectionString.OpenDbConnection())
        {
            string sql = @"
                select  *
                from    insumo i
                join    unidadmedida um on um.id = i.idum
                join    lineainsumo l on l.id = i.idlinea
                left outer join archivo a on a.id = i.idimagen;";

            var insumos = conn.Query<Entities.Insumo, Entities.UnidadMedida,
                Entities.LineaInsumo, Entities.Archivo, Entities.Insumo>(sql, (i, um, l, a)
                    =>
                    {
                        i.UnidadMedida = um; i.Linea = l; i.Fotografia = a ?? new Entities.Archivo();
                        return i;
                    }).ToList(); //Dapper

            return insumos;
        }

这是临时解决方法:

        using (var conn = this.ConnectionString.OpenDbConnection())
        {
            string sql = @"
                select * from insumo;
                select * from unidadmedida;
                select * from lineainsumo;
                select  a.*
                from    archivo a
                join    insumo i on i.idimagen = a.id;";


            var q = conn.QueryMultiple(sql); //Dapper
            var insumos = q.Read<Entities.Insumo>().ToList();
            var ums = q.Read<Entities.UnidadMedida>().ToList();
            var lineas = q.Read<Entities.LineaInsumo>().ToList();
            var archivos = q.Read<Entities.Archivo>().ToList();

            foreach (var i in insumos)
            {
                i.UnidadMedida = ums.FirstOrDefault(c => c.Id == i.IdUm);
                i.Linea = lineas.FirstOrDefault(c => c.Id == i.IdLinea);
                i.Fotografia = archivos.FirstOrDefault(c => c.Id == i.IdImagen) ?? new Entities.Archivo();
            }

            return insumos;
        }

我正在研究ORMLite的代码,似乎可以修改函数 ToCreateTableStatement 来解决我的问题。也许在我的类定义中为每个字段添加一个属性来说明所需的字段创建顺序可以起作用吗?

我正考虑将此添加到 FieldDefinition 代码:

public bool FirstField { get; set; }

添加一个属性来装饰C#字段,如下所示:

[Alias("name")]
public string Name { get; set; }

[Alias("id")]
[PrimaryKey]
[FirstField(true)]
public int Id { get; set; }

然后在创建字段时,代码可以遵循此属性上的值,并允许控制最终字段在表上的位置。

如果我走上了正确的轨道,请告诉我,或者也许还有另一个更优雅的选择。

提前致谢。

1 个答案:

答案 0 :(得分:1)

在每个类上覆盖抽象Id而不是修改ORMLite的源代码似乎更容易。

该项目的时间表很窄,尝试另一种方法。也许对于下一个,我可以找时间尝试@mithz所建议的。