4

これはSOに関する私の最初の質問です。

ORM として EF Code First を使用し、バージョン移行のために FluentMigrator を使用している ASP.NET 4.0 MVC3 プロジェクトがあります。そして、次のような Message エンティティ クラスがあります。

public class Message
{
    [Key]
    [Column("Message_Id")]
    public int Id { get; set; }

    public DateTime CreatedTime { get; set; }

    [Required]
    [StringLength(MaxSubjectLength)]
    public string Subject { get; set; }

    [Required]
    [StringLength(MaxBodyLength)]
    public string Body { get; set; }

    public Link Link { get;set; }
}

カスタム マッピングが定義されておらず、MSSQL Server 2012 データベース テーブル メッセージ:

CREATE TABLE [dbo].[Messages](
    [Message_Id] [int] IDENTITY(1,1) NOT NULL,
    [CreatedTime] [datetime] NOT NULL,
    [Subject] [nvarchar](78) NOT NULL,
    [BodyHtml] [nvarchar](2000) NOT NULL,
    [Link_Id] [int] NULL,
    [Collection_Id] [int] NULL,
    [MessageType] [nvarchar](30) NOT NULL,
 CONSTRAINT [PK_Messages] PRIMARY KEY CLUSTERED 
(
    [Message_Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Messages]  WITH CHECK ADD  CONSTRAINT [FK_Messages_Collection] FOREIGN KEY([Collection_Id])
REFERENCES [dbo].[Collections] ([Id])
GO

ALTER TABLE [dbo].[Messages] CHECK CONSTRAINT [FK_Messages_Collection]
GO

ALTER TABLE [dbo].[Messages]  WITH CHECK ADD  CONSTRAINT [FK_Messages_Link] FOREIGN KEY([Link_Id])
REFERENCES [dbo].[Links] ([Id])
GO

ALTER TABLE [dbo].[Messages] CHECK CONSTRAINT [FK_Messages_Link]
GO

Link_Id、Collection_Id、および MessageType 列は、TPH 継承を行いたいため、そのテーブルにあります (実際には、TPT 継承を行い、TPH に切り替えました。問題は解決すると思いましたが、解決しませんでした)。

今のところ、次のような LinkMessage および CollectionMessage クラスが必要です。

public class LinkMessage : Message
{
    public int? Link_Id { get;set; }
}

public class CollectionMessage : Message
{
    public int? Collection_Id { get;set; }
}

したがって、問題は次のとおりです。リンクナビゲーションプロパティを削除し、プロジェクトを再構築し(データベースを再作成するなど)、単純なクエリを実行すると、継承が定義されていない(つまり、メッセージエンティティのみが存在する)場合でも、var a = DBContext.Messages.ToList(); EFは次のクエリを生成します:

SELECT 
[Extent1].[Message_Id] AS [Message_Id], 
[Extent1].[CreatedTime] AS [CreatedTime], 
[Extent1].[Subject] AS [Subject], 
[Extent1].[BodyHtml] AS [BodyHtml], 
[Extent1].[Link_Id] AS [Link_Id]
FROM [dbo].[Messages] AS [Extent1]

Link_Id がまだ含まれているのはなぜですか? それはもはやモデルではありません。これにより、継承で問題が発生します。上記のサブクラスで TPH (または TPT) 継承を行うと、アプリは「列名 'Link_Id1' が無効です」というエラーで失敗します。Link_Id1 の理由 これはどのように起こりますか?私は完全に混乱しています。「Collection_Id」列は正常に動作します。これら 2 つの列は同一です。データベースを再作成しようとし、アプリのすべてのプロセスを強制終了し(PCを再起動しても)、以前のリビジョンをロードしようとし、そこに Message.Link_Id プロパティを削除し、データを使用して試行し、データなしで試行しました-同じ動作。私は何かをグーグルで検索しようとしましたが、実際には適切な検索クエリを作成する方法さえ知らず、行った検索でも何も得られなかったため、何も得られませんでした.2日目を費やしています...

以下は、彼らが生成しているクエリと SQL です。

var b = DBContext.Messages.OfType<CollectionMessage>();

SELECT 
[Extent1].[Message_Id] AS [Message_Id], 
'0X0X' AS [C1], 
[Extent1].[CreatedTime] AS [CreatedTime], 
[Extent1].[Subject] AS [Subject], 
[Extent1].[BodyHtml] AS [BodyHtml], 
[Extent1].[Collection_Id] AS [Collection_Id], 
[Extent1].[Link_Id1] AS [Link_Id1]
FROM [dbo].[Messages] AS [Extent1]
WHERE [Extent1].[MessageType] = N'CollectionMessage'


var b = DBContext.Messages.OfType<LinkMessage>();

SELECT 
[Extent1].[Message_Id] AS [Message_Id], 
'0X0X' AS [C1], 
[Extent1].[CreatedTime] AS [CreatedTime], 
[Extent1].[Subject] AS [Subject], 
[Extent1].[BodyHtml] AS [BodyHtml], 
[Extent1].[Link_Id] AS [Link_Id], 
[Extent1].[Link_Id1] AS [Link_Id1]
FROM [dbo].[Messages] AS [Extent1]
WHERE [Extent1].[MessageType] = N'LinkMessage'


var b = DBContext.Messages;

SELECT 
[Extent1].[Message_Id] AS [Message_Id], 
CASE WHEN (((CASE WHEN ([Extent1].[MessageType] = N'LinkMessage') THEN cast(1 as bit) ELSE cast(0 as bit) END) <> cast(1 as bit)) AND ((CASE WHEN ([Extent1].[MessageType] = N'CollectionMessage') THEN cast(1 as bit) ELSE cast(0 as bit) END) <> cast(1 as bit))) THEN '0X' WHEN ([Extent1].[MessageType] = N'LinkMessage') THEN '0X0X' ELSE '0X1X' END AS [C1], 
[Extent1].[CreatedTime] AS [CreatedTime], 
[Extent1].[Subject] AS [Subject], 
[Extent1].[BodyHtml] AS [BodyHtml], 
CASE WHEN (((CASE WHEN ([Extent1].[MessageType] = N'LinkMessage') THEN cast(1 as bit) ELSE cast(0 as bit) END) <> cast(1 as bit)) AND ((CASE WHEN ([Extent1].[MessageType] = N'CollectionMessage') THEN cast(1 as bit) ELSE cast(0 as bit) END) <> cast(1 as bit))) THEN CAST(NULL AS int) WHEN ([Extent1].[MessageType] = N'LinkMessage') THEN [Extent1].[Link_Id] END AS [C2], 
CASE WHEN (((CASE WHEN ([Extent1].[MessageType] = N'LinkMessage') THEN cast(1 as bit) ELSE cast(0 as bit) END) <> cast(1 as bit)) AND ((CASE WHEN ([Extent1].[MessageType] = N'CollectionMessage') THEN cast(1 as bit) ELSE cast(0 as bit) END) <> cast(1 as bit))) THEN CAST(NULL AS int) WHEN ([Extent1].[MessageType] = N'LinkMessage') THEN CAST(NULL AS int) ELSE [Extent1].[Collection_Id] END AS [C3], 
[Extent1].[Link_Id1] AS [Link_Id1]
FROM [dbo].[Messages] AS [Extent1]

Link_Id および Link_Id1 列を照会するのはなぜですか? 誰か助けてください、何が足りないのですか?

UPD:カスタム DBInitializer を削除し、Code First で DB を作成すると、「Messages」テーブルに追加の列「Link_Id1」が作成されます。

4

3 に答える 3

4

ここから始めて くださいhttp://msdn.microsoft.com/en-us/data/jj591583.aspx

public Link Link { get;set; }

Link_Id をドラッグ中

于 2013-04-22T14:58:50.117 に答える