Структура сущности, когда многие ко многим содержит данные
Я использую Entity Framework CTP5.
У меня есть такая схема:
- Группа содержит много текстовых описаний.
- Текстовое описание имеет много текстов.
- Язык имеет много текстов.
Итак, есть 4 таблицы. Группы один-ко-многим DE - описаниям многие-ко-многим Текстам многие-к-одному Языки.
Таким образом, у меня есть отношение многие ко многим, где отношение также содержит данные.
Определения Text и TextDescription (поскольку мы можем запрашивать Id для группы и языков, я не добавил их здесь)
public class Text
{
public int TextID { get; set; }
public int TextDescriptionID { get; set; }
public int LanguageID { get; set; }
public string OriginalText { get; set; }
public bool IsValid { get; set; }
public DateTime Added { get; set; }
public DateTime Updated { get; set; }
public Language Language { get; set; }
public TextDescription TextDescription { get; set; }
public static Text GetMissingText(string input)
{
Text text = new Text();
text.OriginalText = "Missing: " + input;
text.IsValid = true;
text.TextDescription = new TextDescription()
{
IsStatic = true,
Name = input,
IsMultiline = false,
};
return text;
}
}
public class TextDescription
{
public int TextDescriptionId { get; set; }
public int TextDescriptionGroupId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool UseHtml { get; set; }
public bool IsMultiline { get; set; }
public bool IsStatic { get; set; }
public TextDescriptionGroup TextDescriptionGroup { get; set; }
public virtual ICollection<Text> Texts { get; set; }
public static TextDescription GetNewItem(int textDescriptionGroupId)
{
var item = new TextDescription();
item.Name = item.Description = "n/a";
item.UseHtml = item.IsMultiline = item.IsMultiline = false;
item.TextDescriptionGroupId = textDescriptionGroupId;
return item;
}
}
При добавлении нового языка или нового текста вставляется... отношение многие ко многим не вставляется в базу данных. (Думаю, это была бы плохая идея, поэтому, в конце концов, если это единственное решение, я смогу это сделать)
Итак, как мне поступить разумно, когда мне нужно извлечь весь текст для определенной группы из базы данных, а также получить перевод, если таковой имеется для этих языков.
Я не могу начать переводить объект, так как возможно, его там нет. Если я начну запрашивать из объекта Text... как выбрать только один язык, не получая сначала все языки.
repo.Find(x =>
x.GroupId == groupId &&
x.Translation.Any(a => a.LanguageID == id.Value)
);
Я заблудился здесь... есть ли какой-нибудь умный способ... так что мне не придется запрашивать базу данных для всех текстов... а затем запросить для каждого элемента... чтобы увидеть, есть ли перевод? или просто сделать новый пустой.
В SQL я бы сделал это так:
SELECT TD.Name, T.OriginalText FROM TextDescriptions TD
LEFT JOIN Texts T ON TD.TextDescriptionId = T.TextDescriptionId
WHERE TextDescriptionGroupId = 41 AND ISNULL(T.LanguageId, 1) = 1
Приведенный выше SQL даст мне элементы, даже если сейчас нет записи, я получаю NULL для этих значений. Затем я мог бы обработать это мой код и избежать ленивой нагрузки.
Но могу ли я получить такое же поведение в Entity Framework. Я мог видеть, что могут быть некоторые проблемы, возможно, для EF4, чтобы сделать отображение..., так как я иду от TextDesciptions к Texts ... и TextDesciptions есть список текстов... но здесь... я хочу только 1 или NULL, или просто новый объект, который еще не был добавлен в базу данных.
С нетерпением жду некоторых интересных ответов.
MVH
1 ответ
На данный момент... если не найдено никакого другого решения, я буду запускать следующий скрипт SQL для вставки пустых записей. Таким образом, я уверен, что запись существует, когда пользователь хочет отредактировать ее, и нет необходимости проверять ее там перед сохранением. Может быть, также избегать некоторых неприятных запросов Linq.
Мне нужно только запустить этот SQL 2 места. При добавлении нового языка или нового нового TextDesciption.
INSERT INTO Texts
SELECT TD.TextDescriptionId, L.LanguageId, '', 0, GETDATE(), GETDATE(), L.TwoLetterISOLanguageName
FROM TextDescriptions TD
INNER JOIN Languages L ON 1 = 1
LEFT JOIN Texts T ON
T.TextDescriptionId = TD.TextDescriptionId AND
T.LanguageId = L.LanguageId
WHERE TextId IS NULL