OrmLite选择跨连接表的多个列

时间:2014-10-20 22:40:03

标签: c# sql servicestack ormlite-servicestack

使用OrmLite填充POCO中的某些列时遇到一些困难。我有三张名为Dog,Bowl和DogBowl的桌子。 DogBowl是一个交叉表,拥有狗和碗的id。

Dogs
    PK Id: int, not null
    Breed: varchar(20), not null
    Name: varchar(20), not null

Bowls
    PK Id: int, not null
    Type: varchar(20), not null
    Color: varchar(20), not null

Dogs_Bowls
    PK: DogId, not null
    PK: BowlId, not null

以下是我已经映射的POCO

public class Dog : IHasId<int>
{
    [AutoIncrement]
    public int Id { get; set; }

    [Required]
    public string Breed { get; set; }

    [Required]
    public string Name { get; set; }
}


public class Bowl : IHasId<int>
{
    [AutoIncrement]
    public int Id { get; set; }

    [Required]
    public string Type { get; set; }

    [Required]
    public string Color { get; set; }
}


public class DogBowl
{
    [Required]
    public int DogId { get; set; }

    [Required]
    public int BowlId { get; set; }

    [Ignore]
    public string DogName { get;set; }

    [Ignore]
    public string BowlColor { get;set; }
}

这是我正在运行的c#代码。

var dogBowl = db.Select<DogBowl>(db
    .From<Dog>()
    .Join<Dog, DogBowl>((d, db) => d.Id == db.DogId)
    .Join<DogBowl, Bowl>((db, b) => db.BowlId == b.Id)
    .Where<Dog>(d => d.Id == 5))
    .ToList();

我想要生成的SQL是:

select
    db.DogId,
    db.BowlId,
    d.Name AS DogName,
    b.Color as BowlColor
from DogBowl db
join dog d on db.DogId = d.Id
join bowl b on db.BowlId = b.Id
where d.Id = 5

我的问题是代码执行后DogBowl.DogName和DogBowl.BowlColor属性为null。我正在使用https://github.com/ServiceStack/ServiceStack.OrmLite中标题为“在连接表中选择多个列”一节中提供的说明,但它不起作用。如何填充DogBowl.DogName和DogBowl.BowlColor属性?

2 个答案:

答案 0 :(得分:4)

生成的SQL可能是正确的。您可以通过检查属性db.GetLastSql()来验证执行后生成的SQL。

问题在于将结果指定为

db.Select<DogBowl> 

,您正在创建DogBowl对象列表。 DogBowl属性DogName和BowlColor将始终为null,因为SQL语句中没有与这些名称完全匹配的字段。 OrmLite不会神奇地弄清楚那里会发生什么 - 你必须让它们按名称匹配。

如果要将结果分配给包含Dog和Bowl字段的“flat”对象,可以定义新的DTO并分配结果,如下所示:

public class FullDogBowl
{
    public int DogId { get; set; }
    public int BowlId { get; set; }
    public string Breed { get; set; }
    public string Name { get; set; }
    public string Type { get; set; }
    public string Color { get; set; }
}

var dogBowl = db.Select<FullDogBowl>(db
    .From<Dog>()
    .Join<Dog, DogBowl>((d, db) => d.Id == db.DogId)
    .Join<DogBowl, Bowl>((db, b) => db.BowlId == b.Id)
    .Where<Dog>(d => d.Id == 5))
    .ToList();

或者,如果您确切地知道要使用的SQL,只需使用它:

string sql = @"select
    db.DogId,
    db.BowlId,
    d.Name AS DogName,
    b.Color as BowlColor
from DogBowl db
join dog d on db.DogId = d.Id
join bowl b on db.BowlId = b.Id
where d.Id = @dog_id ";

var dogBowlList = db.SqlList<DogBowl>(sql, new { dog_id = 5, });

答案 1 :(得分:2)

想要添加到Raul的回答[Ignore]告诉OrmLite完全忽略该属性,所以你重新使用表作为合并的POCO“视图”的方法不会起作用。我建议将结果集POCO拆分为一个单独的POCO,其中包含您想要返回的所有字段:

public class DogBowl
{
    [Required]
    public int DogId { get; set; }

    [Required]
    public int BowlId { get; set; }
}

public class DogBowlInfo
{
    public int DogId { get; set; }

    public int BowlId { get; set; }

    public string DogName { get; set; }

    public string BowlColor { get; set; }
}

现在返回一个填充的结果集:

using (var db = OpenDbConnection())
{
    db.DropAndCreateTable<Dog>();
    db.DropAndCreateTable<Bowl>();
    db.DropAndCreateTable<DogBowl>();

    var dog = new Dog { Breed = "Breed", Name = "Name" };
    var bowl = new Bowl { Color = "Color", Type = "Type" };
    db.Save(dog);
    db.Save(bowl);
    db.Insert(new DogBowl { DogId = dog.Id, BowlId = bowl.Id });

    var dogBowl = db.Select<DogBowlInfo>(
         db.From<Dog>()
          .Join<Dog, DogBowl>((d, b) => d.Id == b.DogId)
          .Join<DogBowl, Bowl>((d, b) => d.BowlId == b.Id)
          .Where<Dog>(d => d.Id == dog.Id));

    dogBowl.PrintDump();
}