【问题标题】:Can this be done with Entity Framework 4 ? If not, what can do this?这可以用 Entity Framework 4 来完成吗?如果没有,有什么办法可以做到这一点?
【发布时间】:2010-08-28 00:58:52
【问题描述】:

我正在制作一个简单的trivial pursuit game。我不确定是否(以及如何)我可以使用 EF4 执行以下操作:-

我的表结构如下。

表格:TrivialPursuitQuestion

=> ID
=> Unique Question
=> AnswerId
=> AnswerType (ie. Geography, Entertainment, etc).

表:GeographyAnswer

=> ID
=> Place Name
=> LatLong

表:娱乐回答:

=> ID
=> Name
=> BordOn
=> DiedOn
=> Nationality .. and other meta data

...等等..

所以当一个人问一个独特的问题时......存储的过程能够弄清楚它是什么类型的答案(即 AnswerType 字段)......并因此查询正确的表。

EG.

SELECT @AnswerId = AnswerId, @AnswerType = AnswerType
FROM TrivialPursuitQuestions
WHERE UniqueQuestion = @Question

IF @AnswerId > 0 AND @AnswerType > 0 BEGIN
    IF @AnswerType = 1
        SELECT * 
        FROM GeographicAnswers 
        WHERE AnswerId = @AnswerID

    IF @AnswerType = 2
        SELECT * 
        FROM EntertainmentAnswer
        WHERE AnswerId = @AnswerId

    ... etc ...
END

现在 .. 我不确定如何使用 EF 执行此操作。首先,存储过程现在可以返回多种结果类型..所以我不确定这是否真的很糟糕。

然后我想,也许存储过程应该返回多个记录集......除了一个包含结果的记录集之外的所有记录集......因为根据设计,只会找到一种答案类型......

EG.

-- Same SELECT as above...


IF @AnswerId > 0 BEGIN
    SELECT * 
    FROM GeographicAnswers 
    WHERE AnswerId = CASE @AnswerId WHEN 1 THEN @AnswerID ELSE 0 END

    SELECT * 
    FROM EntertainmentAnswer 
    WHERE AnswerId = CASE @AnswerId WHEN 2 THEN @AnswerID ELSE 0 END

    ... etc ...
END

这将返回 6 个(多个)记录集......但其中只有一个应该有一些数据。

现在,如果这是一个更好的解决方案......这是否可以使用 EF4 以及如何实现?

我试图避免两次往返数据库,还必须弄清楚要尝试检索的内容......我不想弄清楚......我希望有一些聪明的人对系统进行建模很聪明,可以说“哦!你这是正确的答案'。有点像答案工厂(ala 工厂模式),但使用 Sql Server + EF4。

有人有什么想法吗?

【问题讨论】:

    标签: sql-server entity-framework architecture entity-framework-4


    【解决方案1】:

    在 EF 设计器中,您可以创建一个名为 Answer 的实体,然后创建从名为 GeographyAnswerEntertainmentAnswer 的答案派生的实体...在答案实体中使用鉴别器 AnswerType /em>。添加Question 实体。将问题中的关联添加到Answer,将其标记为 1:1。让 EF 为您的数据库生成 DDL。

    现在您可以通过question.Answer 获取Answer 以获得Question。您可以查看 Answer 的类型并显示相应的 UI。

    不过,这也引出了一个问题,如果它是问题和答案之间的 1:1 对应关系,为什么不使用单个实体 QuestionAnswer 并从中派生出 QuestionAnswerGeographyQuestionAnswerEntertainment、... 现在您可以轻松选择特定类型的Questions:例如dataContext.QuestionAnswers.ofType<QuestionAnswerGeography>()

    这是一个实体图,适用于多个问题可能共享一个答案的情况:

    此模型将允许您执行如下查询:

      var geographyQuestions = objectContext.Answers.OfType<Geography>().SelectMany(answer => answer.Questions);
    

    这个模型生成的DDL是:-

    -- Creating table 'Answers'
    CREATE TABLE [dbo].[Answers] (
        [Id] int IDENTITY(1,1) NOT NULL
    );
    GO
    
    -- Creating table 'Questions'
    CREATE TABLE [dbo].[Questions] (
        [Id] int IDENTITY(1,1) NOT NULL,
        [AnswerId] int  NOT NULL,
        [QuestionText] nvarchar(max)  NOT NULL
    );
    GO
    
    -- Creating table 'Answers_Geography'
    CREATE TABLE [dbo].[Answers_Geography] (
        [PlaceName] nvarchar(max)  NOT NULL,
        [LatLong] nvarchar(max)  NOT NULL,
        [Id] int  NOT NULL
    );
    GO
    
    -- Creating table 'Answers_Entertainment'
    CREATE TABLE [dbo].[Answers_Entertainment] (
        [Name] nvarchar(max)  NOT NULL,
        [BornOn] datetime  NULL,
        [DiedOn] datetime  NULL,
        [Id] int  NOT NULL
    );
    GO
    
    -- --------------------------------------------------
    -- Creating all PRIMARY KEY constraints
    -- --------------------------------------------------
    
    -- Creating primary key on [Id] in table 'Answers'
    ALTER TABLE [dbo].[Answers]
    ADD CONSTRAINT [PK_Answers]
        PRIMARY KEY CLUSTERED ([Id] ASC);
    GO
    
    -- Creating primary key on [Id] in table 'Questions'
    ALTER TABLE [dbo].[Questions]
    ADD CONSTRAINT [PK_Questions]
        PRIMARY KEY CLUSTERED ([Id] ASC);
    GO
    
    -- Creating primary key on [Id] in table 'Answers_Geography'
    ALTER TABLE [dbo].[Answers_Geography]
    ADD CONSTRAINT [PK_Answers_Geography]
        PRIMARY KEY CLUSTERED ([Id] ASC);
    GO
    
    -- Creating primary key on [Id] in table 'Answers_Entertainment'
    ALTER TABLE [dbo].[Answers_Entertainment]
    ADD CONSTRAINT [PK_Answers_Entertainment]
        PRIMARY KEY CLUSTERED ([Id] ASC);
    GO
    
    -- --------------------------------------------------
    -- Creating all FOREIGN KEY constraints
    -- --------------------------------------------------
    
    -- Creating foreign key on [AnswerId] in table 'Questions'
    ALTER TABLE [dbo].[Questions]
    ADD CONSTRAINT [FK_QuestionAnswer]
        FOREIGN KEY ([AnswerId])
        REFERENCES [dbo].[Answers]
            ([Id])
        ON DELETE NO ACTION ON UPDATE NO ACTION;
    
    -- Creating non-clustered index for FOREIGN KEY 'FK_QuestionAnswer'
    CREATE INDEX [IX_FK_QuestionAnswer]
    ON [dbo].[Questions]
        ([AnswerId]);
    GO
    
    -- Creating foreign key on [Id] in table 'Answers_Geography'
    ALTER TABLE [dbo].[Answers_Geography]
    ADD CONSTRAINT [FK_Geography_inherits_Answer]
        FOREIGN KEY ([Id])
        REFERENCES [dbo].[Answers]
            ([Id])
        ON DELETE NO ACTION ON UPDATE NO ACTION;
    GO
    
    -- Creating foreign key on [Id] in table 'Answers_Entertainment'
    ALTER TABLE [dbo].[Answers_Entertainment]
    ADD CONSTRAINT [FK_Entertainment_inherits_Answer]
        FOREIGN KEY ([Id])
        REFERENCES [dbo].[Answers]
            ([Id])
        ON DELETE NO ACTION ON UPDATE NO ACTION;
    GO
    

    【讨论】:

    • @Hightechrider :感谢您的回答 :) 我有点困惑 - 主要是第 3 段。我理解AbstractAnswer 的想法,然后创建从其继承的具体类:例如。 GeographicAnswer : AbstractAnswer 。这正是我要做的,但不想使开头的问题复杂化。但是,如果我这样做,EF 如何才能真正调用一个存储的过程,它将返回正确的每个问题的类型..并将其序列化到适当的具体类中?我注意到您使用了语法 ofType&lt;TEntity&gt;() .. 但我仍然不确定这是如何编程的。
    • 我建议您在这里根本不需要存储过程,它们在此示例中没有提供额外的好处。 Ef 可以构造一个高效的查询来为您检索实体,它将处理创建正确类型的实体并从映射表中对其进行水合。
    • @hightechrider 啊! wikid :) 但我还是不明白。我试过在谷歌上寻找一些帮助(例如实体框架“ofType”,但我没有找到解释我想要做什么的东西。你有任何可以帮助的链接..或扩展你的答案一些屏幕截图/代码?
    • 当然你也可以选择除了TablePerType之外的其他映射。这里的博客也可能对您有所帮助:robbagby.com/entity-framework/…
    • @Hightechrider 哇!我从来没有新的你能做到这一点;)太棒了!即使这样也有效:var answers = db.Answers.Include("Question").ToList(); 并且每个答案都是强类型的。弗拉克。我。 WIKID :) 欢呼队友 :)
    猜你喜欢
    • 2022-11-24
    • 2015-08-04
    • 2016-12-12
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    相关资源
    最近更新 更多