Если вы объясните, какой заказ клиента вы хотите и хотите ли вы указывать полную цену заказа или цену каждого товара в этом заказе, мы можем указать более конкретно. Я должен был сделать некоторые предположения (см. Комментарии):
select
c.Company
, o.ShipDate as this_is_max_ship_date_of_customer
, o.OrderID --Added OrderID so you know what the price is associated with
, sum(oi.price) this_is_sum_of_prices_of_the_order
--if you want the price of a particular item, you can add ItemID beneath OrderID and also group by it
from dbo.Customers c
join dbo.Orders o
on c.CustomerID = o.CustomerID
join dbo.OrderItems oi
on o.OrderID = oi.OrderID
where o.Deleted = 0
and o.ShipDate in (select max(inner_o.ShipDate) from dbo.Orders inner_o
where inner_o.Company = c.Company
group by inner_o.Company)
--This subquery points to the outer reference - a useful trick
-- it means only the most recent ShipDate for the customer is shown
and o.OrderId in (select max(inner_o2.OrderId) from dbo.Orders inner_o2
where inner_o2.Company = c.Company
and inner_o2.ShipDate = o.ShipDate
group by inner_o2.Company)
--This subquery is doing the same thing, but for your OrderId
--Unfortunately you don't specify enough in your question, so
-- I have to assume you only want their most recent order
--To prevent an ShipDate that is not of the OrderId you care about,
-- I had to add the second where clause here
group by
c.Company,
o.ShipDate,
o.OrderId
Как насчет того, чтобы писать два дополнительных метода:
public static void AddPhoneNumber(this Contact contact, PhoneType type);
и
public static void AddPhoneNumber(this Person person, PhoneType type);
Инструмент для очистки взглядов мне.
Если существует некоторый общий код между этими двумя, извлеките это в отдельный метод.
Сделать Contact
и Person
реализуйте единый интерфейс - говорят IContactWithPhoneNumbers
- и затем запишите дополнительный метод "для этого интерфейса".
public interface IContactWithPhoneNumbers {}
public class Contact : IContactWithPhoneNumbers {}
public class Person : IContactWithPhoneNumbers {}
public static void AddPhoneNumber(this IContactWithPhoneNumbers obj) {}
Чтение комментариев (объекты от SDK и не доступны для редактирования). Я, вероятно, сделал бы что-то вроде этого:
public class Util
{
//common util method
public static void AddPhoneNumber(object obj, string phoneNumber)
{
if(obj is Contact)
((Contact)contact).Phones.Add(phoneNumber);
else if(obj is Person)
((Person)contact).Phones.Add(phoneNumber);
}
//extension method for Person
public static void AddPhoneNumber(this Person p, string phoneNumber)
{
AddPhoneNumber((object)p, phoneNumber);
}
//extension method for Contact
public static void AddPhoneNumber(this Contact c, string phoneNumber)
{
AddPhoneNumber((object)c, phoneNumber);
}
}
Я действительно думаю лучшая практика, хотя то, когда Вы имеете контроль над основными объектами, должно было бы реализовать единый интерфейс.
Вы можете сделать свой метод расширения универсальным, например:
public static void AddPhoneNumberToContact<T>(
this T contact,
PhoneType type,
String number
)
{
PhoneRow pr = PhoneRow.CreateNew();
pr.SetDefaults();
pr.PtypeIdx = type;
pr.PhoneNumber = number;
((T)contact).Phones.Add(pr);
pr = null;
}
Вы не сможете использовать блокировку
, потому что "T" не является ссылочным типом, как требуется оператором блокировки ", поэтому вам, возможно, придется вернуть какое-то значение.
Если он жалуется на невозможность разрешить метод Phones для типа T, вы можете:
Передать некоторый делегат функции , который принимает тип T, ничего не возвращает и выполняет действие ((T) contact) .Phones.Add (pr);
.
Или вы можете создать интерфейс, подобный следующему:
public interface IPhoneable
{
IList<Phone> Phones();
}
Затем, когда у вас есть этот интерфейс, вы можете добавить следующее к своему универсальному методу расширения:
public static void AddPhoneNumberToContact<T>(
this T contact,
PhoneType type,
String number
) where T : IPhoneable {...}
Здесь T
по-прежнему является универсальным типом, но теперь ваш метод AddPhoneNumberToContact требует, чтобы в любом случае T
- это,он наследуется от интерфейса IPhoneable, который вы только что определили для использования метода Phones ().
См. также Метод расширения C # для общих коллекций .