您需要注意两件事。你想存储什么,什么是有效的。并非所有可能的值都是有效的。
在这种情况下,CommentDiscussion 必须包含 Claim 或 ForumThread 引用,但不能同时设置。
实体:
public class Claim
{
public int Id { get; set; }
public string Name { get; set; }
public CommentDiscussion CommentDiscussion { get; set; }
}
public class ForumThread
{
public int Id { get; set; }
public string Name { get; set; }
public CommentDiscussion CommentDiscussion { get; set; }
}
public class CommentDiscussion
{
public int Id { get; set; }
public int? ClaimId { get; set; }
public Claim Claim { get; set; }
public int? ForumThreadId { get; set; }
public ForumThread ForumThread { get; set; }
}
配置
public class ClaimConfiguration : EntityTypeConfiguration<Claim>
{
public ClaimConfiguration()
{
HasKey( e => e.Id );
Property( e => e.Name )
.IsRequired( )
.HasMaxLength( 100 );
}
}
public class ForumThreadConfiguration : EntityTypeConfiguration<ForumThread>
{
public ForumThreadConfiguration()
{
HasKey( e => e.Id );
Property( e => e.Name )
.IsRequired( )
.HasMaxLength( 100 );
}
}
public class CommentDiscussionConfiguration : EntityTypeConfiguration<CommentDiscussion>
{
public CommentDiscussionConfiguration()
{
HasKey( e => e.Id );
HasOptional( e => e.Claim )
.WithRequired( m => m.CommentDiscussion )
.Map( cfg => cfg.MapKey( nameof( CommentDiscussion.ClaimId ) ) );
HasOptional( e => e.ForumThread )
.WithRequired( m => m.CommentDiscussion )
.Map( cfg => cfg.MapKey( nameof( CommentDiscussion.ForumThreadId ) ) );
}
}
并且确保CommentDiscussion 具有一个对Claim 或ForumThread 的引用的验证:
public class ModelContext : DbContext
{
// Der Kontext wurde für die Verwendung einer ModelContext-Verbindungszeichenfolge aus der
// Konfigurationsdatei ('App.config' oder 'Web.config') der Anwendung konfiguriert. Diese Verbindungszeichenfolge hat standardmäßig die
// Datenbank 'ConsoleApp7.Model.ModelContext' auf der LocalDb-Instanz als Ziel.
//
// Wenn Sie eine andere Datenbank und/oder einen anderen Anbieter als Ziel verwenden möchten, ändern Sie die ModelContext-Zeichenfolge
// in der Anwendungskonfigurationsdatei.
public ModelContext()
: base( "name=ModelContext" )
{
}
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
modelBuilder.Configurations.Add( new ClaimConfiguration( ) );
modelBuilder.Configurations.Add( new ForumThreadConfiguration( ) );
modelBuilder.Configurations.Add( new CommentDiscussionConfiguration( ) );
base.OnModelCreating( modelBuilder );
}
protected override bool ShouldValidateEntity( DbEntityEntry entityEntry )
{
return base.ShouldValidateEntity( entityEntry );
}
protected override DbEntityValidationResult ValidateEntity( DbEntityEntry entityEntry, IDictionary<object, object> items )
{
if ( entityEntry.Entity is CommentDiscussion )
{
if ( !entityEntry.CurrentValues.GetValue<int?>( nameof( CommentDiscussion.ClaimId ) ).HasValue && !entityEntry.CurrentValues.GetValue<int?>( nameof( CommentDiscussion.ForumThreadId ) ).HasValue )
{
var list = new List<System.Data.Entity.Validation.DbValidationError>( );
list.Add( new System.Data.Entity.Validation.DbValidationError( nameof( CommentDiscussion.Claim ), "Claim or ForumThread is required" ) );
list.Add( new System.Data.Entity.Validation.DbValidationError( nameof( CommentDiscussion.ForumThread ), "Claim or ForumThread is required" ) );
return new System.Data.Entity.Validation.DbEntityValidationResult( entityEntry, list );
}
if ( entityEntry.CurrentValues.GetValue<int?>( nameof( CommentDiscussion.ClaimId ) ).HasValue && entityEntry.CurrentValues.GetValue<int?>( nameof( CommentDiscussion.ForumThreadId ) ).HasValue )
{
var list = new List<System.Data.Entity.Validation.DbValidationError>( );
list.Add( new System.Data.Entity.Validation.DbValidationError( nameof( CommentDiscussion.Claim ), "Only Claim or ForumThread is possible, not both" ) );
list.Add( new System.Data.Entity.Validation.DbValidationError( nameof( CommentDiscussion.ForumThread ), "Only Claim or ForumThread is possible, not both" ) );
return new System.Data.Entity.Validation.DbEntityValidationResult( entityEntry, list );
}
}
return base.ValidateEntity( entityEntry, items );
}
}
检查
using ( var context = new ModelContext() )
{
CommentDiscussion discussion = new CommentDiscussion( );
context.Set<CommentDiscussion>( ).Add( discussion );
try
{
context.SaveChanges( );
}
catch ( Exception ex )
{
Console.WriteLine( ex.ToString() );
}
Claim claim = new Claim( );
ForumThread forumThread = new ForumThread( );
claim.CommentDiscussion = discussion;
forumThread.CommentDiscussion = discussion;
try
{
context.SaveChanges( );
}
catch ( Exception ex )
{
Console.WriteLine( ex.ToString( ) );
}
}
更新
这里是为模型生成的迁移
public partial class InitialCreate : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Claims",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(nullable: false, maxLength: 100),
ClaimId = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.CommentDiscussions", t => t.ClaimId)
.Index(t => t.ClaimId);
CreateTable(
"dbo.CommentDiscussions",
c => new
{
Id = c.Int(nullable: false, identity: true),
ClaimId = c.Int(),
ForumThreadId = c.Int(),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.ForumThreads",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(nullable: false, maxLength: 100),
ForumThreadId = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.CommentDiscussions", t => t.ForumThreadId)
.Index(t => t.ForumThreadId);
}
public override void Down()
{
DropForeignKey("dbo.ForumThreads", "ForumThreadId", "dbo.CommentDiscussions");
DropForeignKey("dbo.Claims", "ClaimId", "dbo.CommentDiscussions");
DropIndex("dbo.ForumThreads", new[] { "ForumThreadId" });
DropIndex("dbo.Claims", new[] { "ClaimId" });
DropTable("dbo.ForumThreads");
DropTable("dbo.CommentDiscussions");
DropTable("dbo.Claims");
}
}