Подтвердить что ты не робот

Простой внутренний результат соединения с Dapper?

Кажется, я не могу найти документацию или примеры для моей проблемы (теперь вы искали какое-то время). Я думаю, что моя проблема довольно проста, поэтому здесь идет.

У меня две таблицы. Моя основная таблица называется Персоны, а вторичная таблица - PersonEntries. Для каждого человека в таблице Person я могу иметь 0 или более записей в таблице PersonEntries. Вот так.

Table: Person
Id
Name

Table: PersonEntry
PersonId
CheckinTime
CheckoutTime

У меня есть два объекта вроде этого

public class Person {
  public string Name;
  public List<PersonEntry> PersonEntries;
}

public class PersonEntry {
  public DateTime CheckinTime;
  public DateTime CheckoutTime;
}

Если бы я должен был получить его из базы данных в мои классы С#, как бы я это сделал? Я могу сопоставить одну таблицу со своим классом С# и сделать это для каждой таблицы, но тогда я остаюсь в соответствии с тем, какие записи сопоставляются с тем, кто человек.

Я видел несколько примеров сопоставления ONE PersonEntry с ONE Person, проблема в том, что у меня отношение "нуль-ко-многим". У моего лица есть СПИСОК элементов PersonEntry.

4b9b3361

Ответ 1

Вы можете сделать что-то подобное (см. https://www.tritac.com/blog/dappernet-by-example):

public class Shop {
  public int? Id {get;set;}
  public string Name {get;set;}
  public string Url {get;set;}
  public IList<Account> Accounts {get;set;}
}

public class Account {
  public int? Id {get;set;}
  public string Name {get;set;}
  public string Address {get;set;}
  public string Country {get;set;}
  public int ShopId {get;set;}
}

var lookup = new Dictionary<int, Shop>()
conn.Query<Shop, Account, Shop>(@"
                SELECT s.*, a.*
                FROM Shop s
                INNER JOIN Account a ON s.ShopId = a.ShopId                    
                ", (s, a) => {
                     Shop shop;
                     if (!lookup.TryGetValue(s.Id, out shop)) {
                         lookup.Add(s.Id, shop = s);
                     }
                     if (shop.Accounts == null) 
                         shop.Accounts = new List<Account>();
                     shop.Accounts.Add(a);
                     return shop;
                 }
                 ).AsQueryable();
var resultList = lookup.Values;

Ответ 2

У меня есть это решение. Сначала я бы рассмотрел добавление столбца Id в оба класса:

public class Person {
  public int Id;
  public string Name;
  public List<PersonEntry> PersonEntries;
}

public class PersonEntry {
  public int PersonId;
  public DateTime CheckinTime;
  public DateTime CheckoutTime;
}

Затем я бы запросил каждую таблицу, позвольте мне создать целый метод с тем, как я обычно работаю с Dapper:

protected IEnumerable<Person> GetAll(string connString)
{
   IEnumerable<Person> result;
   using (IDbConnection dbConnection = new SqlConnection(connString))
   {
      dbConnection.Open();
      try
      {
         result = dbConnection.Query<Person>("SELECT * FROM Person");
         foreach(var person in result)
         {
             person.PersonEntries = dbConnection.Query<PersonEntry>("SELECT * FROM PersonEntry WHERE PersonId = @id", new {id = person.Id}).ToList();
         }
      }
      catch (Exception ex)
      {
         throw ex;
      }
   }

   return result;
}

Второе решение с использованием динамического

var list = dbConnection.Query("SELECT * FROM Person p inner join PersonEntry pe ON p.Id = pe.PersonId");
var result = new List<Person>();
foreach(var item in list)
{
   var tmp = result.SingleOrDefault(x=>x.Id == item.Id);
   if(tmp == null)
   {
      tmp = new Person{Id = item.Id, Name = item.Name, PersonEntries = new List<PersonEntry>()};
      result.Add(tmp);
   }
   tmp.PersonEntries.Add(new PersonEntry{PersonId = item.Id, CheckinTime = item.CheckinTime, CheckoutTime = item.CheckoutTime });
}
return result;