Я стараюсь максимально избегать использования значений NULL в базе данных. Это означает, что символьные поля всегда не равны нулю. То же самое для числовых полей, особенно для обозначения денег или аналогичных (доли, единицы и т. Д.).
У меня есть 2 исключения:
Я также иногда использовал явные битовые поля для «неизвестно» / «не set "(например, JobDescriptionCode и IsEmployeed).
У меня есть несколько основных причин, по которым:
Мои предпочтения по умолчанию:
. Возможно, вам придется немного подправить это, поскольку я собирался сойти с дистанции, но есть о парочке важных вещей, о которых следует помнить. Если ваши отношения настроены правильно в вашем dbml, вы должны иметь возможность неявно выполнять внутренние соединения и просто получать доступ к данным через исходную таблицу. Кроме того, левые соединения в LINQ не так просты, как мы могли бы надеяться, и вам нужно пройти через синтаксис DefaultIfEmpty, чтобы это произошло. Я создал здесь анонимный тип, но вы можете захотеть поместить в класс DTO или что-то в этом роде. Я также не знал, что вы хотите сделать в случае нулей, но вы можете использовать ?? синтаксис для определения значения, которое будет присвоено переменной, если значение равно нулю. Дайте мне знать, если у вас возникнут дополнительные вопросы ...
var query = (from a in context.Appointment
join b in context.AppointmentFormula on a.AppointmentId equals b.AppointmentId into temp
from c in temp.DefaultIfEmpty()
join d in context.AppointmentForm on a.AppointmentID equals e.AppointmentID into temp2
from e in temp2.DefaultIfEmpty()
where a.RowStatus == 1 && c.RowStatus == 1 && a.Type == 1
select new {a.AppointmentId, a.Status, a.Type, a.Title, c.Days ?? 0, a.Type.Description, e.FormID ?? 0}).OrderBy(a.Type);
SELECT A.X, B.Y
FROM A JOIN B ON A.X = B.Y
Этот вызов метода linq (для соединения) сгенерирует указанное выше соединение.
var query = A.Join
(
B,
a => a.x,
b => b.y,
(a, b) => new {a.x, b.y} //if you want more columns - add them here.
);
SELECT A.X, B.Y
FROM A LEFT JOIN B ON A.X = B.Y
Эти вызовы метода linq (для GroupJoin, SelectMany, DefaultIfEmpty) будет производить указанное выше левое соединение
var query = A.GroupJoin
(
B,
a => a.x,
b => b.y,
(a, g) => new {a, g}
).SelectMany
(
z => z.g.DefaultIfEmpty(),
(z, b) =>
new { x = z.a.x, y = b.y } //if you want more columns - add them here.
);
Ключевой концепцией здесь является то, что методы Linq производят результаты в иерархической форме, а не в плоских формах строки-столбца.
GroupBy
выдает результаты, сформированные в виде иерархии с ключом группировки, соответствующим коллекции элементов (которая может быть не пустой). Предложение SQL GroupBy
создает ключ группировки с агрегированными значениями - нет никакой подгруппы для работы. GroupJoin
создает иерархическую форму - родительская запись соответствует коллекции дочерних записей (которая может быть пустой). Sql LEFT JOIN
создает родительскую запись, соответствующую каждой дочерней записи, или пустую дочернюю запись, если других совпадений нет. Чтобы получить форму Sql из формы Linq, нужно распаковать коллекцию дочерних записей с помощью SelectMany
- и обработать пустые коллекции дочерних записей с помощью DefaultIfEmpty
. И вот моя попытка определить этот sql-код в вопросе:
var query =
from a in Appointment
where a.RowStatus == 1
where a.Type == 1
from b in a.AppointmentFormula.Where(af => af.RowStatus == 1).DefaultIfEmpty()
from d in a.TypeRecord //a has a type column and is related to a table named type, disambiguate the names
from e in a.AppointmentForm.DefaultIfEmpty()
order by a.Type
select new { a.AppointmentId, a.Status, a.Type, a.Title, b.Days, d.Description, e.Form }
Если вы хотите сохранить (NOLOCK) подсказки, я написал в блоге удобное решение с использованием методов расширения в C#. Обратите внимание, что это то же самое, что добавить подсказки nolock к каждой таблице в запросе.