这是我在ServiceStack ORMLite做实验的第三天。我的示例项目过去只使用Dapper,现在它是Dapper和ServiceStack ORMLite的混合体,兼具这两个世界的优点。
昨晚我在为一个Dapper的查询而挣扎。它基本上是一个选择连接4个表,在ORMLite的代码出现之前运行ok。现在,它在针对对象的表映射方面一再失败。它没有破坏,只是给对象分配了错误的值。
我不得不继续前进,因此作为一个临时的解决方法,我所做的是在不使用SQL的情况下使用Dapper的QueryMultiple执行每个选择,然后在C#上一个接一个地加入结果。
请别笑了。我知道这当然不是最好的解决办法。然而,它仍然只对DB进行了一次访问,但感觉并不自然。当行数很可能增加时,这将是性能问题。
今天早上,我想我找到了问题的根源:我正在使用ORMLite下垂和创建表,并注意到字段顺序与我预期的不太一样。在编写ORMLite代码之前,我只是手动运行SQL脚本,因此我决定了字段的顺序。由于我的项目需要支持MySql、Postgresql和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; }然后,在创建字段的时候,代码可以跟踪此类属性上的值,并允许控制表中最后字段的位置。
请让我知道,如果我是正确的轨道,或者,也许有另一个更优雅的选择比这一个。
提前谢谢。
发布于 2013-01-31 20:08:01
只覆盖每个类上的抽象Id,而不是修改ORMLite的源代码,似乎更容易。
为了尝试另一种方法,这个项目的时间表很窄。也许在下一次,我能找到时间去尝试@mithz善意的建议。
https://stackoverflow.com/questions/14629563
复制相似问题