Используйте <br />
.
Чтобы вставить HTML в тег с Angular, используйте: <span class="card-title" style="font-size: 12px" [innerHTML]="item.itemName"></span>
почему не мог разработчики 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
за один шаг также. Иерархическое формирование результатов запроса является большим.
Вероятно, потому что выражения 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
}
Это - то, что я подразумеваю под синтаксическим сахаром. Выражения запроса не добавляют ничего нового для языка, они просто обеспечивают более легкий способ использовать существующие функции языка.