2014-10-20 1 views
2

У меня возникли трудности с заполнением некоторых столбцов в POCO с использованием OrmLite. У меня три таблицы по имени Dog, Bowl и DogBowl. DogBowl - это таблица соединений и содержит идентификатор Dog and Bowl.OrmLite Выбор нескольких столбцов Входящие таблицы

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?

ответ

4

Сгенерированный SQL может быть правильным. Вы можете проверить сгенерированный SQL после выполнения, проверив свойство db.GetLastSql().

Проблема заключается в том, что, назначая результат как

db.Select<DogBowl> 

, вы создаете список объектов DogBowl. Свойства DogBowl DogName и BowlColor всегда будут нулевыми, потому что в инструкции SQL нет поля, которое точно соответствует этим именам. OrmLite не будет волшебным образом выяснять, что там происходит - вы должны иметь их по имени.

Если вы хотите присвоить результат «плоской» объект с полями из собаки и Шара, вы могли бы определить новый 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, }); 
+0

OK это имеет смысл. Я пытался повторно использовать мой DogBowl poco, чтобы избавить себя от необходимости создавать другой класс. Теперь я вижу, что атрибут Ignore полностью игнорирует заполнение этих полей любым использованием poco. Я закончил переименование DogBowl poco на DogBowlJunction, чтобы провести DogId и BowlId, а затем создал новый poco с именем DogBowl для хранения свойств DogId, BowlId, DogName и BowlColor. – Halcyon

2

Хотел добавить к ответу Рауля что [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; } 
} 

который теперь возвращает населенный с ResultSet:

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(); 
}