代码之家  ›  专栏  ›  技术社区  ›  Pure.Krome

这可以用实体框架4完成吗?如果没有,怎么办?

  •  2
  • Pure.Krome  · 技术社区  · 14 年前

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

    我有如下的表格结构。

    表:TrivialProsuit问题

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

    表:地理学家

    => ID
    => Place Name
    => LatLong
    

    表:娱乐回答:

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

    …等。。

    所以当一个人问一个独特的问题…存储过程能够确定它是什么类型的答案(即answer type字段)。因此查询正确的表。

    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
    

    现在。。我不知道怎么用英孚。首先,存储过程现在可以返回多个结果类型。所以我不确定这是否真的很糟糕。

    所以我想,也许存储过程应该返回多个记录集。除一个记录集外,所有记录集都包含结果…因为根据设计,只有一种答案类型会被找到…

    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能做到这一点吗?如何做到这一点?

    我试着避免去DB做两次往返旅行,同时也要弄清楚要尝试和检索什么……我不想非得想出来…我希望通过一些智能建模,该系统足够智能,可以说“哦!这是正确的答案。有点像一个应答工厂(ALA工厂模式),但使用的是SQL Server+EF4。

    有人有什么想法吗?

    1 回复  |  直到 14 年前
        1
  •  2
  •   Ian Mercer    14 年前

    在EF设计器中,您可以创建一个名为 answer的实体,然后创建从answer派生的实体,名为 geographyswer , entertainmentanswer ,…在应答实体中使用鉴别器。添加 问题 实体。将关联从问题添加到 answer ,标记为1:1。让ef为您的数据库生成ddl。

    现在,您可以执行 question.answer 以获取 answer for a question 。您可以查看 answer 的类型,并显示相应的用户界面。

    尽管如此,这也引出了一个问题,如果问题和答案之间是1:1的对应关系,为什么不让一个实体 questunswer->code>and derive s from that to create questunswergeography->code>, questunswerentertainment->code>,…现在,您可以轻松地选择特定类型的 问题: dataContext.QuestUnswers.of type<QuestUnswergeography>(). for example.

    下面是一个可由多个问题共享答案的案例的实体图:

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

    var geography questions=objectcontext.answers.oftype<geography>().selectmany(answer=>answer.questions);
    < /代码> 
    
    

    此模型生成的DDL是:-

    创建“答案”表 创建表[dbo]。[answers]。( [id]int标识(1,1)不为空 ; 去 --创建“问题”表 创建表[dbo]。[questions]( [id]int标识(1,1)不为空, [answerid]int不为空, [问题文本]nvarchar(max)不为空 ; 去 --创建“答案\地理”表 创建表[dbo]。[answers_geography]。( [placename]nvarchar(max)不为空, [latlong]nvarchar(max)不为空, [id]int不为空 ; 去 --创建“答案\娱乐”表 创建表[dbo]。[answers\u entertainment]( [名称]nvarchar(max)不为空, [Bornon]日期时间为空, [diedon]日期时间为空, [id]int不为空 ; 去 --————————————————————————————————————————————————————————————————————————————————————————————————————————————--- --创建所有主键约束 --————————————————————————————————————————————————————————————————————————————————————————————————————————————--- --在“答案”表中的[ID]上创建主键 更改表[dbo]。[answers] 添加约束[pk_answers] 主键聚集([id]asc); 去 --在“问题”表中的[ID]上创建主键 更改表[dbo]。[问题] 添加约束[pk_问题] 主键聚集([id]asc); 去 --在“答案\地理位置”表中的[ID]上创建主键 更改表[DBO]。[答案\地理位置] 添加约束[pk_answers_geography] 主键聚集([id]asc); 去 --在“答案\娱乐”表中的[ID]上创建主键 更改表[DBO]。[回答娱乐] 添加限制[pk_answers_entertainment] 主键聚集([id]asc); 去 --————————————————————————————————————————————————————————————————————————————————————————————————————————————--- --创建所有外键约束 --————————————————————————————————————————————————————————————————————————————————————————————————————————————--- --在“问题”表中的[answerid]上创建外键 更改表[dbo]。[问题] 添加约束 外键([answerid]) 参考文献[DBO]。[答案] [(ID]) 删除时不执行任何操作更新时不执行任何操作; --正在为外键“fk_questunswer”创建非聚集索引 创建索引[ix fk_Questunswer] 关于[DBO]。[问题] ([答案]); 去 --在“答案\地理位置”表中的[ID]上创建外键 更改表[DBO]。[答案\地理位置] 添加约束[fk_geography_inherits_answer] 外键([id]) 参考文献[DBO]。[答案] [(ID]) 删除时不执行任何操作更新时不执行任何操作; 去 --在“答案\娱乐”表中的[ID]上创建外键 更改表[DBO]。[回答娱乐] 添加约束[FK_Entertainment_Inherits_Answer] 外键([id]) 参考文献[DBO]。[答案] [(ID]) 删除时不执行任何操作更新时不执行任何操作; 去 < /代码>
    然后创建从名为GeographyAnswer,EntertainmentAnswer,…使用鉴别器AnswerType在应答实体中. 添加Question实体。将问题中的关联添加到回答,标记为1:1。让ef为数据库生成DDL。

    现在你可以做question.Answer得到回答对于一个问题. 你可以看看回答并显示相应的用户界面。

    然而,这也引出了一个问题,如果问题和答案之间是1:1的对应关系,为什么不有一个单独的实体呢?QuestionAnswer从中衍生出QuestionAnswerGeography,QuestionAnswerEntertainment,…现在你可以选择Questions特别类型的:dataContext.QuestionAnswers.ofType<QuestionAnswerGeography>()例如。

    下面是一个可由多个问题共享答案的案例的实体图: alt text

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

      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