我遇到了一个问题,我使用ServiceStack.OrmLite.Sqlite.Windows在表和视图之间构建连接查询,并且发出的sql包含一个带有如下列的select语句:
SELECT "Country"."Id", "Country"."Code", "Country"."Title", ...
据我所知,这是完全有效的SQL,但是当我调用IDbConnection.Select<Country>(expr)
时,Ormlite并没有正确地将字段映射到POCO。 (我得到了正确数量的结果,但每个对象中的所有字段都为空)
以下是我正在使用的代码,遗憾的是,我无法通过简化示例来显示相同的问题:
Repository.cs
public List<Country> FilterValidCountries(ProgrammingMapFilter filter) {
using (_db.BeginTransaction()) {
var q = _db.From<Country>()
.Join<Mid, ProgrammingMapView>((mid, map) => mid.Id == map.Mid)
.Join<Country, Mid>((country, mid) => country.Code == mid.CountryCode)
.OrderBy(x => x.Title);
if (filter.ProductId.HasValue)
q = q.Where<ProgrammingMapView>(x => x.ProductId == filter.ProductId);
if (filter.ProtocolId.HasValue)
q = q.Where<ProgrammingMapView>(x => x.ProtocolId == filter.ProtocolId);
return _db.Select(q);
}
}
模型
public class Country {
public int Id { get; set; }
public string Code { get; set; }
public string Title { get; set; }
public string ShortTitle { get; set; }
public DateTime? ModifiedOn { get; set; }
public int? ModifiedBy { get; set; }
}
public class Mid {
public int Id { get; set; }
public string CountryCode { get; set; }
public DateTime? ModifiedOn { get; set; }
public int? ModifiedBy { get; set; }
}
public class ProgrammingMapView {
public int ProductId { get; set; }
public int ProtocolId { get; set; }
public int Mid { get; set; }
}
架构
create table Country (
Id integer primary key,
Code text,
Title text,
ShortTitle text,
ModifiedOn text,
ModifiedBy integer
);
create table Mid (
Id integer primary key,
CountryCode text,
ModifiedOn text,
ModifiedBy integer
);
create view ProgrammingMapView as
select
p.Id ProductId
, pt.Id ProtocolId
, m.Id Mid
from Mid m
join MidProduct mprod on (mprod.RegisteredMid = m.Id)
join Product p on (p.Id = mprod.ProductId)
join MidProtocol mprot on (mprot.RegisteredMid = m.Id)
join ProtocolType pt on (pt.Id = mprot.ProtocolId)
join ProductProtocol pp on (pp.ProductId = p.Id and pp.ProtocolTypeId = pt.Id)
;
发出的SQL
SELECT "Country"."Id", "Country"."Code", "Country"."Title", "Country"."ShortTitle", "Country"."ModifiedOn", "Country"."ModifiedBy"
FROM "Country"
INNER JOIN "ProgrammingMapView" ON ("Mid"."Id" = "ProgrammingMapView"."Mid")
INNER JOIN "Mid" ON ("Country"."Code" = "Mid"."CountryCode")
WHERE ("ProgrammingMapView"."ProductId" = 87)
ORDER BY "Country"."Title" ASC
我将问题跟踪到ServiceStack.OrmLite.OrmLiteWriteExtensions.cs:323(v4.0.30)。在TryGuessColumnIndex()
中,当Ormlite调用dataReader.GetName(i)
时,GetName方法始终返回&#34; Country&#34;。 (不是&#34; Country.Id&#34;或&#34; Country.Title&#34;)
private static int TryGuessColumnIndex(string fieldName, IDataReader dataReader)
{
if (OrmLiteConfig.DisableColumnGuessFallback)
return NotFound;
var fieldCount = dataReader.FieldCount;
for (var i = 0; i < fieldCount; i++)
{
var dbFieldName = dataReader.GetName(i);
....
这让我相信我安装的System.Data.Sqlite.Core库并没有正确地解析引用的表限定标识符。 System.Data.Sqlite.Core(v1.0.93)在不使用servicestack.ormlite的情况下显示相同的行为:
using (var cn = new SQLiteConnection(string.Format("Data Source={0};Version=3;", dbPath2)))
{
cn.Open();
var query = @"
SELECT ""Country"".""Id"", ""Country"".""Code"", ""Country"".""Title"", ""Country"".""ShortTitle"", ""Country"".""ModifiedOn"", ""Country"".""ModifiedBy""
FROM ""Country"" INNER JOIN ""ProgrammingMapView"" ON (""Mid"".""Id"" = ""ProgrammingMapView"".""Mid"") INNER JOIN ""Mid"" ON (""Country"".""Code"" = ""Mid"".""CountryCode"")
WHERE (""ProgrammingMapView"".""ProductId"" = 87)
ORDER BY ""Country"".""Title"" ASC
";
using (var cmd = new SQLiteCommand(query, cn))
{
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
for (var i = 0; i < reader.FieldCount; i++)
{
Console.Write(reader.GetName(i) + ", ");
}
Console.WriteLine();
}
}
}
}
输出
Country, Country, Country, Country, Country, Country,
Country, Country, Country, Country, Country, Country,
在ServiceStack.Ormlite或System.Data.Sqlite的配置中是否有一些错过,允许IDataReader.GetName(i)
返回正确的列名(而不仅仅是表名)?