我遇到1:0..1关系的问题。我收到错误:' TestContext.Environments'中的实体参与“PortalEnvironment_Ba环境”#39;关系。 0相关的' PortalEnvironment_BaEnvironment_Target'被找到。 1' PortalEnvironment_BaEnvironment_Target'是预期的。
我有3个表,实现了Table-Per-Type。
以下是我用于测试的SQL / C#代码的简化版本:
CREATE TABLE dbo.EnvironmentBase(
EnvironmentId int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED
);
CREATE TABLE dbo.BAEnvironment(
EnvironmentId int NOT NULL PRIMARY KEY CLUSTERED,
CONSTRAINT FK_BAEnvironment_EnvironmentBase FOREIGN KEY(EnvironmentId)
REFERENCES dbo.EnvironmentBase (EnvironmentId) ON DELETE CASCADE
);
CREATE TABLE dbo.PortalEnvironment(
EnvironmentId int NOT NULL PRIMARY KEY CLUSTERED,
BAEnvironmentId int NOT NULL,
CONSTRAINT FK_PortalEnvironment_BAEnvironment FOREIGN KEY(BAEnvironmentId)
REFERENCES dbo.BAEnvironment (EnvironmentId) ,
CONSTRAINT FK_PortalEnvironment_EnvironmentBase FOREIGN KEY(EnvironmentId)
REFERENCES dbo.EnvironmentBase (EnvironmentId) ON DELETE CASCADE
);
在处理我的问题时,我使用了以下文章来帮助One to Zero/One Relationship in EF使用Option2Mimic(独立关联),因为这似乎最适合我的情况。但是,我得到上面显示的错误。
波苏斯:
public abstract partial class Environment
{
public int Id { get; set; } // EnvironmentId (Primary key)
public Environment()
{
InitializePartial();
}
partial void InitializePartial();
}
public partial class BaEnvironment : Environment
{
// MAY have a portal environment
public virtual PortalEnvironment PortalEnvironment { get; set; } // PortalEnvironment.FK_PortalEnvironment_BAEnvironment
public BaEnvironment()
{
InitializePartial();
}
partial void InitializePartial();
}
public partial class PortalEnvironment : Environment
{
// MUST have a BAMS environment
public virtual BaEnvironment BaEnvironment { get; set; } // PortalEnvironment.FK_PortalEnvironment_BAEnvironment
public PortalEnvironment()
{
InitializePartial();
}
partial void InitializePartial();
}
配置:
public partial class EnvironmentMap : EntityTypeConfiguration<Environment>
{
public EnvironmentMap() : this("dbo")
{
}
public EnvironmentMap(string schema)
{
ToTable("EnvironmentBase", schema);
HasKey(x => x.Id);
Property(x => x.Id).HasColumnName(@"EnvironmentId")
.HasColumnType("int").IsRequired()
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(x => x.Ordinal).HasColumnName(@"Ordinal")
.HasColumnType("tinyint").IsRequired();
InitializePartial();
}
partial void InitializePartial();
}
public partial class BaEnvironmentMap : EntityTypeConfiguration<BaEnvironment>
{
public BaEnvironmentMap() : this("dbo")
{
}
public BaEnvironmentMap(string schema)
{
ToTable("BAEnvironment", schema);
InitializePartial();
}
partial void InitializePartial();
}
public partial class PortalEnvironmentMap : EntityTypeConfiguration<PortalEnvironment>
{
public PortalEnvironmentMap() : this("dbo")
{
}
public PortalEnvironmentMap(string schema)
{
ToTable("PortalEnvironment", schema);
//Property(x => x.BaEnvironmentId).HasColumnName(@"BAEnvironmentId")
.HasColumnType("int").IsRequired()
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
// Foreign keys
HasRequired(a => a.BaEnvironment).WithOptional(b => b.PortalEnvironment)
.Map(c => c.MapKey(@"BAEnvironmentId"));
InitializePartial();
}
partial void InitializePartial();
}
我似乎对TPT没有任何问题,只是与PortalEnvironment和BAEnvironment之间的关系。 BAEnvironment和PortalEnvironment之间的关系是1:0..1,因此BAEnviroment可能有一个相关的PortalEnvironment,但所有PortalEnvironments必须有一个相关的BAEnvironment。
我的问题似乎很简单,但我一直在来回,只是没有达到流畅的api的正确组合来解决它。
值得注意的是,我是一名DBA,而不是应用程序开发人员。只是坚持这个,因为没有其他人会这样做。
答案 0 :(得分:0)
EF6不支持备用密钥,因此要求外键列为1..1关系中的实体密钥。您可以将FK标记为唯一,但在EF模型中,您仍然可以在BAEnvironment和Portal Environment之间建立1..many关系。
例如
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
namespace Ef6Test
{
public abstract partial class Environment
{
public int Id { get; set; } // EnvironmentId (Primary key)
public Environment()
{
InitializePartial();
}
partial void InitializePartial();
}
public partial class BaEnvironment : Environment
{
// MAY have a portal environment
[InverseProperty("BaEnvironment")]
public virtual ICollection<PortalEnvironment> PortalEnvironments { get; } = new HashSet<PortalEnvironment>();
public BaEnvironment()
{
InitializePartial();
}
partial void InitializePartial();
}
public partial class PortalEnvironment : Environment
{
// MUST have a BAMS environment
[ForeignKey("BaEnvironmentID")]
public virtual BaEnvironment BaEnvironment { get; set; } // PortalEnvironment.FK_PortalEnvironment_BAEnvironment
[Required(), Index(IsUnique = true)]
public int BaEnvironmentID { get; set; }
public PortalEnvironment()
{
InitializePartial();
}
partial void InitializePartial();
}
class Db : DbContext
{
public DbSet<Environment> Environment { get; set; }
public DbSet<BaEnvironment> BaEnvironment { get; set; }
public DbSet<PortalEnvironment> PortalEnvironment { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Environment>().ToTable("Environment");
modelBuilder.Entity<BaEnvironment>().ToTable("BaEnvironment");
modelBuilder.Entity<PortalEnvironment>().ToTable("PortalEnvironment");
modelBuilder.Entity<PortalEnvironment>().HasRequired<BaEnvironment>(e => e.BaEnvironment).WithMany();
base.OnModelCreating(modelBuilder);
}
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<Db>());
using (var db = new Db())
{
db.Database.Log = m => Console.WriteLine(m);
db.Database.Initialize(true);
}
Console.WriteLine("Hit any key to exit");
Console.ReadKey();
}
}
}