Простой внутренний результат соединения с 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.
Ответы
Ответ 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;