X中的实体参与Y关系。找到了0个相关的Target。 1目标是预期的

时间:2017-11-30 18:35:04

标签: c# sql-server entity-framework foreign-keys table-per-type

我遇到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,而不是应用程序开发人员。只是坚持这个,因为没有其他人会这样做。

1 个答案:

答案 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();
        }
    }
}