【问题标题】:OrmLite Selecting Multiple Columns Across Joined TablesOrmLite 跨连接表选择多列
【发布时间】:2017-03-24 04:26:32
【问题描述】:

我在使用 OrmLite 填充 POCO 中的某些列时遇到了一些困难。我有三个名为 Dog、Bowl 和 DogBowl 的表。 DogBowl 是一个连接表,包含 Dog 和 Bowl 的 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 属性为空。我正在使用标题为“在连接表中选择多个列”一节中https://github.com/ServiceStack/ServiceStack.OrmLite 上提供的说明,但它不起作用。如何填充 DogBowl.DogName 和 DogBowl.BowlColor 属性?

【问题讨论】:

    标签: c# sql servicestack ormlite-servicestack


    【解决方案1】:

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

    问题是通过将结果分配为 ​​

    db.Select<DogBowl> 
    

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

    如果您想将结果分配给包含 Dog 和 Bowl 字段的“平面”对象,您可以定义一个新的 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, });
    

    【讨论】:

    • 好的,这是有道理的。我试图重用我的 DogBowl poco 来避免自己创建另一个类。现在我看到 Ignore 属性将完全忽略使用 poco 填充这些字段。我最终将 DogBowl poco 重命名为 DogBowlJunction 来保存 DogId 和 BowlId,然后创建了一个名为 DogBowl 的新 poco 来保存 DogId、BowlId、DogName 和 BowlColor 属性。
    【解决方案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();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-21
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多