이것은 ServiceStack ORMLite로 실험 한 제 3 번째 날입니다. Dapper와 함께 일했던 샘플 프로젝트, 이제는 Dapper와 ServiceStack ORMLite를 모두 사용하여 두 세계를 최대한 활용합니다.
어젯밤에 저는 Dapper 쿼리로 고심하고있었습니다. 그것은 ORMLite의 코드가 들어 오기 전에 기본적으로 네 개의 테이블을 합치는 ok입니다. 이제는 객체에 대한 테이블 매핑에 계속해서 실패하고 있습니다. 그것은 단지 객체에 잘못된 값을 할당하는 것입니다.
나는 임시 대책으로 SQL의 조인없이 Dapper의 QueryMultiple을 사용하여 4 개의 각 select를 실행하고 결과를 하나씩 결합하는 C #으로 이동해야했습니다.
제발 웃지 마세요. 나는 이것이 최선의 해결책이 아니라는 것을 알고 있습니다. 아직까지는 DB를 한 번 방문하지만 자연 스럽지는 않습니다. 행 수가 가장 늘어날 경우 성능 문제가됩니다.
오늘 아침에 나는 내 문제의 근원을 발견했다고 생각한다 : 나는 ORMLite를 사용하여 테이블을 작성하고 생성하는 중이다. 그리고 필드 순서가 내가 예상했던 것과 상당히 다르다는 것을 알아 차렸다. ORMLite 코드를 사용하기 전에 수동으로 SQL 스크립트를 실행하기 때문에 필드의 순서를 결정했습니다. 내 프로젝트가 MySql, Postgresql 및 SQL Server를 최종 사용자의 욕구로 지원해야하므로 이러한 스크립트의 세 가지 버전을 동기화하는 것이 어려울 것입니다. ORMLite로이 과정을 자동화하고 그것을 최대한 활용하고 싶습니다.
이제 제 이론에 대해 설명하겠습니다. 당신들은 전문가들이 내가 옳았는지 잘못했는지를 결정할 것입니다. 조인을 사용하는 Dapper의 쿼리는 명명 규칙을 기반으로 각 테이블의 결과를 각 클래스에 매핑합니다. "Id"또는 "id"필드가 테이블의 첫 번째 필드가 될 것으로 예상합니다.
Dapper는 명명 규칙 ( "Id"대신 PK로 "IdProduct")을 따르지 않는 테이블을 처리하는 "SplitOn"옵션을 가지고 있지만 실제로는 아무런 제어가 없기 때문에 제 경우에는 사용할 수 없습니다. 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; }
그런 다음 필드를 만들 때 코드는 해당 속성의 값을 따르고 테이블의 최종 필드 위치를 제어 할 수 있습니다.
제가 옳은 길로 들어갔다면 나에게 알려주 길 바란다. 아니면이 대안이 좀 더 우아 할 수도있다.
미리 감사드립니다.
ORMLite의 소스 코드를 수정하는 대신 모든 클래스의 추상 ID를 재정의하는 것이 더 쉬운 것처럼 보입니다.
프로젝트의 일정은 다른 접근법을 시도하기에 좁습니다. 아마도 다음 번에는 @mithz가 제안하는 것을 시도 할 시간을 찾을 수 있습니다.