当多对多保存数据时的实体框架
我正在使用实体框架 CTP5。
我有一个这样的架构:
- 一个组包含许多文本描述。
- 一个文本描述有很多文本。
- 一种语言有许多文本。
所以有4张桌子。 组一对多描述多对多文本多对一语言。
所以我有一个多对多关系,其中该关系还保存数据。
文本和文本描述的定义(因为我们可以查询组和语言的 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;
}
}
当添加新语言或插入新文本时...多对多关系不会插入到数据库中。 (认为这将是一个坏主意,所以最后,如果这是唯一的解决方案,我可以做到)
那么当我需要获取所有文本
我无法启动翻译对象,因为它可能不存在。如果我开始从文本实体查询...我如何只选择一种语言而不先获取所有语言。
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。然后我可以处理它我的代码并避免延迟加载。
但是我可以在实体框架中获得相同的行为吗?我可以看到 EF4 进行映射可能会出现一些问题...因为我要从 TextDeciptions 转到文本...并且 TextDeciptions 有一个文本列表...但是在这里...我只想要 1或 NULL,或者只是尚未添加到数据库中的新实体。
期待一些有趣的答案。
MVH
I'm using Entity Framework CTP5.
I have a schema like this:
- A group contains many textdescriptions.
- A textdescriptions has many texts.
- A Language has many texts.
So there are 4 tables.
Groups one-to-many DEscriptions many-to-many Texts many-to-one Languages.
So I have a many-to-many relationship where the relation also holds data.
Definitions of Text and TextDescription ( since we can query on the Id for Group and Languages I havent added them here )
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;
}
}
When adding either a new language or a new text is inserted ... the many to many relation is not inserted into the database. (Think it would be a bad idea, so in the end, if thats the only solution, I could be able to that)
So how do I handle this in a smart way when I need to fetch all the text for a specific group from the database, but also get the translation if there are one for that languages.
I can't start fra the translation object, since its possible its not there. If I start to query from the Text entity ... how do I only select one language without getting all languages first.
repo.Find(x =>
x.GroupId == groupId &&
x.Translation.Any(a => a.LanguageID == id.Value)
);
I'm lost here ... any there any smart way ... so I wont have to query the database for all the Texts ... and then a query for each item ... to see if there are a translation? or else just make a new empty one.
In SQL I would do it like this:
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
The above SQL will give me the elements even if there is not record now, I get a NULL for these values. I could then handle that it my code and avoid lazy load.
But can I get the same behavior in Entity Framework. I could see there would be some problems maybe for EF4 to do the mapping ... since I'm going from TextDesciptions to Texts ... and TextDesciptions have a List of Texts ... but here ... I only want either 1 or NULL, or just a new Entity that havent been added to the database yet.
Looking forward to some interesting answers.
mvh
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
现在...如果没有找到其他解决方案,我将运行以下 SQL 脚本来插入空记录。这样,当用户想要编辑记录时,我可以确定该记录就在那里,并且在保存之前不必确保它在那里。也许还可以避免一些令人讨厌的 Linq 查询。
我只需要运行这个 SQL 2 个地方。添加新语言或新 TextDescription 时。
For now ... if no other solution is found I will be running the follow SQL script to insert empty records. This way I'm sure the record is there when a user wants to edit it and dont have to ensure its there before saving it. Maybe also avoiding some naste Linq query.
I only have to run this SQL 2 places. When adding a new Language or new a new TextDesciption.