これは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」が作成されます。