当多对多保存数据时的实体框架

发布于 2024-10-12 01:10:28 字数 3021 浏览 3 评论 0原文

我正在使用实体框架 CTP5。

我有一个这样的架构:

  • 一个组包含许多文本描述。
  • 一个文本描述有很多文本。
  • 一种语言有许多文本。

所以有4张桌子。 一对多描述多对多文本多对一语言

my model

所以我有一个多对多关系,其中该关系还保存数据。

文本和文本描述的定义(因为我们可以查询组和语言的 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.

my model

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

甜宝宝 2024-10-19 01:10:28

现在...如果没有找到其他解决方案,我将运行以下 SQL 脚本来插入空记录。这样,当用户想要编辑记录时,我可以确定该记录就在那里,并且在保存之前不必确保它在那里。也许还可以避免一些令人讨厌的 Linq 查询。

我只需要运行这个 SQL 2 个地方。添加新语言或新 TextDescription 时。

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

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.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文