SqlExpression <t> .Join()和列名</t>的问题

时间:2014-08-27 18:51:57

标签: sqlite system.data.sqlite ormlite-servicestack

我遇到了一个问题,我使用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)返回正确的列名(而不仅仅是表名)?

0 个答案:

没有答案