Прошу прощения за длину, пожалуйста.Кроме того, это абсолютно гипотетическая ситуация, не требующая объяснений, и примеры кода не должны тщательно анализироваться для обеспечения полной точности.
Итак, .Net играет хорошо, когда у вас есть простой, прямой LINQ:
Invoice tbl_invoice = from invoice in DbContext.Invoice
where invoice.RecordID == 1
select invoice;
Предполагается, что класс Invoice существует следующим образом:
[Table]
public class Invoice
{
[Column]
public int RecordID {get; set;}
[Column]
public DateTime RecordDate {get; set;}
}
УчитываяПри выполнении примера LINQ вышеупомянутый класс будет инстанцирован с соответствующими значениями в атрибутах атрибута Column.
Давайте немного продвинем запрос:
var purchases = (from invoice in DbContext.Invoice
join order in DbContext.Order on invoice.RecordID equals order.InvoiceID
select new ProductPurchase
{
invoice.RecordID,
invoice.RecordDate,
order.PartID,
order.Quantity
})
.ToList(); // this is used to create a BindingList<ProductPurchase>
Должно быть два класса, которые напоминают следующее:
[Table]
public class Order
{
[Column]
public int InvoiceID {get; set;}
[Column]
public string OrderID {get; set;}
[Column]
public string Quantity {get; set;}
}
[Table]
public class ProductPurchase : Invoice
{
[Column]
public int InvoiceID {get; set;}
[Column]
public string PartID {get; set;}
[Column]
public string Quantity {get; set;}
}
Цель во втором примере - создатьBindingList<T>
, чтобы данные могли использоваться в качестве источника данных.Итак, со вторым примером LINQ мы могли бы сделать следующее:
BindingList<ProductPurchase> purchases = new BindingList<ProductPurchase>(purchases);
Мы не можем сделать это так легко, как кажется.Мы должны наследовать конкретные классы, чтобы это работало.На мой взгляд, это очень неэлегантно.Я подумал, было бы неплохо, если бы я мог создать интерфейс. Что-то вроде:
[Table]
public interface IInvoice
{
[Column]
public int RecordID {get; set;}
[Column]
public DateTime RecordDate {get; set;}
}
Теперь предположим, что есть аналогичный интерфейс IOrder, я мог бы создать конкретный класс ProductPurchaseследующим образом:
[Table]
public class ProductPurchase : IInvoice, IOrder
{ }
... IF [TableAttribute()]
были разрешены на интерфейсах.
Допустим, я хочу включить join
в PartID в tblParts, который будет извлекать PartsDescription и PartsCost;только один базовый (конкретный или абстрактный) класс может быть унаследован.Похоже, вам нужно создать кучу ненужных дериваций, чтобы иметь возможность разместить соединения.Есть ли альтернатива?Я устал от использования DataTable / DataView в качестве источника данных для DataGridView.Было бы намного проще использовать классы, которые я создал, в качестве отображений.
Один пример задачи, которую я пытаюсь выполнить:
- Вывод списка записей в DataGridView с отображением определенных объединенных данных.
- Пользователь дважды щелкает по выбранному представлению строки таблицы данных.
- Новая WinForm теперь отображает запрошенную информацию из нескольких объединенных таблиц
На шаге 2, когда пользователь выбирает Счет, я преобразую DataGridRowView в DataRow.Не так уж и плохо.Но когда я заканчиваю запрос, у меня появляется анонимный тип данных, который можно использовать для создания экземпляра новой DataTable и заполнения значений DataRow.
Привязка DataRow к новой WinForm не так проста, как привязка класса.Таким образом, мой вопрос и любопытство об альтернативах.Любые идеи будут полезны.
РЕДАКТИРОВАТЬ: Несколько ссылок, которые объясняют немного больше:
РЕДАКТИРОВАТЬ 2:
Допустим, у меня есть запрос из 3 таблиц:
tblInvoices :
InvoiceID |InvoiceDate |Баланс |Платный |PaidDate
tblPurchaseItem :
PartNumber |InvoiceID |PartCost |PartDescription
tblInventory : PartNumber |OnHands |Заказать |Restock
Предположим, что есть 3 класса, украшенные атрибутом отображения [Table] со всеми соответствующими атрибутами отображения [Column] {get;задавать;}.
У меня может быть метод, похожий на следующий:
public static BindingList<InvoiceDetails> GetInvoiceDetails (int InvoiceID)
{
// LINQ is probably incorrect - feel free to post corrections :)
IList<InvoiceDetails> invDetails = (from purchItems in DbContext.PurchaseItemsMap
join invoices in DbContext.Invoices
on purchItems.InvoiceID equals invoices.InvoiceID
join invItems in DbContext.InventoryItemsMap
on purchItems.PartNumber equals invItems.PartNumber
where purchItems.InvoiceID == InvoiceID
where invItems.Restock == true
select new InvoiceDetails
{
invoices.InvoiceID,
purchItems.PartDescription,
purchItems.PartCost,
invItems.OnHands
})
.ToList();
return new BindingList(invDetails);
}
Чтобы это работало, мне понадобится следующее:
[Table]
public class InvoiceDetails : PurchaseItems
{ // invoices column getters & setters }
[Table]
public class PurchaseItems : InventoryItems
{ // purchasItems column getters & setters }
[Table]
public class InventoryItems
{ // inventoryItems column getters & setters }
Теперь, что болеебессмысленны?Необходимость создавать странные комбинации производных классов, которые могли бы создать кошмар обслуживания;или, гипотетически, создайте интерфейсы для отображения таблиц и просто получите классы, такие как InvoiceDetails, следующим образом:
public class InvoiceDetails : IInventoryItems, IPurchaseItems, IInvoices
{ }