Почему Linq делает соединения по-другому

Используйте <br />.

Чтобы вставить HTML в тег с Angular, используйте: <span class="card-title" style="font-size: 12px" [innerHTML]="item.itemName"></span>

5
задан user52110 11 February 2009 в 14:32
поделиться

2 ответа

почему не мог разработчики Linq делать вещи простыми (больше sql как)

Они могли иметь. Но Вашим определением простых (как sql программист) не является то же как определение программиста OO простых. Linq (в C#) является технологией запроса для программистов OO, сначала. Пример этого - то, почему выбор является последним. Это должно выполнить правила объема в C# и поддержку intellisense в редакторе.

Эти программисты, возможно, не добираются LEFT JOIN (и будьте действительно смущены, если Вы говорите LEFT OUTER JOIN - взгляды там являются некоторым различием, как каждый наследовался другому).

То, что они действительно понимают, GROUP JOIN, который ведет себя подобным образом.

List<int> myInts = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<int> myOtherInts = new List<int>() { 1, 3, 5, 7, 9, 11, 13 };
//
var query = from i in myInts
    join j in myOtherInts on i equals j into g
    select new {key = i, myGroup = g};
//
foreach (var grouping in query)
{
  Console.WriteLine("--{0}", grouping.key);
  foreach (var x in grouping.myGroup)
    Console.WriteLine(x);
}

Все это DefaultIfEmpty материал делает, распаковывают группу - выравнивание результатов в форму строки/столбец - далеко от естественной иерархической формы программиста OO. DefaultIfEmpty не семантически необходимо для получения до результатов.

Вот тот же запрос в форме метода - который компилятор генерирует от вышеупомянутого и который я предпочитаю:

var query = myInts.GroupJoin(
    myOtherInts,
    i => i,
    j => j,
    (i, g) => new { key = i, myGroup = g }
);

Вы могли заявить это с точки зрения его примера?

Этот запрос дает Вам клиентов с их заказами как приложенный набор. Набор заказов мог бы быть пустым. Если у Вас будет 50 клиентов и 1 000 заказов, то у Вас будет 50 клиентов в результате.

from c in dc.Customers
join o in dc.Orders on c.custid equals o.custid into someOrders
select new CustomerWithOrders()
  {theCustomer = c, theOrders = someOrders};

Этот запрос дает Вам строку CustomerOrder. Если у клиента будет 5 заказов, то клиент появится 5 раз, каждый раз, подобранный к различному порядку. Если у клиента будет 0 заказов, то клиент будет казаться когда-то подобранным к пустому порядку. Если у Вас будет 50 клиентов и 1 000 заказов, то у Вас будет 50-1049 строк после соединения, и значение элемента в результате трудно определить.

from c in dc.Customers
join o in dc.Orders on c.custid equals o.custid into temp
from x in temp.DefaultIfEmpty()
select new CustomerOrderHybrid() {theCustomer = c, theOrder = x}

Если они реализовали left join, это потребовало бы формы результата второго примера. После того как я использовал group join, который лучше, я не реализовал бы left join за один шаг также. Иерархическое формирование результатов запроса является большим.

5
ответ дан 14 December 2019 в 19:27
поделиться

Вероятно, потому что выражения Linq являются просто синтаксическим сахаром в компиляторе, который переводит их в вызовы метода. Таким образом, синтаксис запроса является текучей абстракцией объектно-ориентированной системы.

Так как Вы на самом деле не пишете SQL, там обязаны быть случаями, где базовая технология ведет себя по-другому. Добавление подобного SQL 'левого соединения', вероятно, намного более трудно, чем Вы думаете.


Некоторые люди очевидно не знают, как выражения Linq работают, таким образом, вот дальнейшее объяснение.

Если я посещаю этот тестовый урок:

public class Class1
{
    public List<string> list = new List<string>() { "test", "test1", "test2" };

    public void test_lambda()
    {
        var test = list.Where(l => l == "test1");
    }

    public void test_linq()
    {
        var test = from l in list
                   where l == "test2"
                   select l;
    }
}

list.Where(l => l == "test2") компилируется в тот же код как from l in list where l == "test2" select l. В обоих случаях компилятор генерирует анонимных делегатов метода:

.method public hidebysig instance void test_lambda() cil managed
{
    .maxstack 8
    L_0000: ldarg.0 
    L_0001: ldfld class [mscorlib]System.Collections.Generic.List`1<string> Class1::list
    L_0006: ldsfld class [System.Core]System.Func`2<string, bool> Class1::CS$<>9__CachedAnonymousMethodDelegate1
    L_000b: brtrue.s L_001e
    L_000d: ldnull 
    L_000e: ldftn bool Class1::<test_lambda>b__0(string)
    L_0014: newobj instance void [System.Core]System.Func`2<string, bool>::.ctor(object, native int)
    L_0019: stsfld class [System.Core]System.Func`2<string, bool> Class1::CS$<>9__CachedAnonymousMethodDelegate1
    L_001e: ldsfld class [System.Core]System.Func`2<string, bool> Class1::CS$<>9__CachedAnonymousMethodDelegate1
    L_0023: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Where<string>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [System.Core]System.Func`2<!!0, bool>)
    L_0028: pop 
    L_0029: ret 
}

.method public hidebysig instance void test_linq() cil managed
{
    .maxstack 8
    L_0000: ldarg.0 
    L_0001: ldfld class [mscorlib]System.Collections.Generic.List`1<string> Class1::list
    L_0006: ldsfld class [System.Core]System.Func`2<string, bool> Class1::CS$<>9__CachedAnonymousMethodDelegate3
    L_000b: brtrue.s L_001e
    L_000d: ldnull 
    L_000e: ldftn bool Class1::<test_linq>b__2(string)
    L_0014: newobj instance void [System.Core]System.Func`2<string, bool>::.ctor(object, native int)
    L_0019: stsfld class [System.Core]System.Func`2<string, bool> Class1::CS$<>9__CachedAnonymousMethodDelegate3
    L_001e: ldsfld class [System.Core]System.Func`2<string, bool> Class1::CS$<>9__CachedAnonymousMethodDelegate3
    L_0023: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Where<string>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [System.Core]System.Func`2<!!0, bool>)
    L_0028: pop 
    L_0029: ret 
}

Это - то, что я подразумеваю под синтаксическим сахаром. Выражения запроса не добавляют ничего нового для языка, они просто обеспечивают более легкий способ использовать существующие функции языка.

0
ответ дан 14 December 2019 в 19:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: