Entity Framework 5.0 zusammengesetzter Fremdschlüssel zu Nicht-Primärschlüssel - ist das möglich?

Ich verwende Entity Framework 5.0.0.0 in einer .net 4.5-Konsolenanwendung und muss auf eine Datenbank mit zwei Tabellen zugreifen, zwischen denen eine Fremdschlüsselbeziehung besteht.

Das Seltsame daran ist, dass der Fremdschlüssel dazwischen liegtB(Almost1, Almost2) undA(Almost1, Almost2) nicht vonB(AId) zuA(AId). Dies ist vom SQL Server als erlaubtAlmost1 undAlmost2 kombiniert sind einzigartig und keine sind nullable (auf TabelleA Zumindest - aufB Sie sind wie es ist eine optionale Beziehung, aber das ist von by).

Hier einige SQL-Anweisungen zum Erstellen dieser Situation:

CREATE TABLE [dbo].[A](
    [AId] [int] IDENTITY(1,1) NOT NULL,
    [Almost1] [int] NOT NULL,
    [Almost2] [int] NOT NULL,
 CONSTRAINT [PK_A] PRIMARY KEY CLUSTERED 
(
    [AId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
 CONSTRAINT [A_Constraint] UNIQUE NONCLUSTERED 
(
    [Almost1] ASC,
    [Almost2] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[B](
    [BId] [int] IDENTITY(1,1) NOT NULL,
    [Almost1] [int] NULL,
    [Almost2] [int] NULL,
 CONSTRAINT [PK_B] PRIMARY KEY CLUSTERED 
(
    [BId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

ALTER TABLE [dbo].[B] ADD  CONSTRAINT [FK_A_B] FOREIGN KEY([Almost1], [Almost2])
REFERENCES [dbo].[A] ([Almost1], [Almost2])

Die Sache ist, es scheint, dass es von Entity Framework nicht erlaubt ist - ist dies der Fall oder definiere ich mein Modell einfach nicht richtig?

Hier ist meine c #:

public class MyContext : DbContext
{
    public MyContext(string connectionString) : base(connectionString)
    {
        MyAs = Set<A>();
        MyBs = Set<B>();
    }

    public DbSet<A> MyAs { get; private set; }
    public DbSet<B> MyBs { get; private set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        var aEntity = modelBuilder.Entity<A>();
        aEntity.ToTable("A");
        aEntity.HasKey(a => a.AId);

        var bEntity = modelBuilder.Entity<B>();
        bEntity.ToTable("B");
        bEntity.HasKey(a => a.BId);
        bEntity
            .HasOptional(b => b.A)
            .WithMany(a => a.Bs)
            .Map(m => m.MapKey("Almost1", "Almost2"));
    }
}

public class A
{
    public int AId { get; set; }
    public int Almost1 { get; set; }
    public int Almost2 { get; set; }
    public virtual ICollection<B> Bs { get; private set; }
    public void AddB(B b)
    {
        if (b == null) throw new ArgumentNullException("b");
        if (Bs == null) Bs = new List<B>();
        if (!Bs.Contains(b)) Bs.Add(b);
        b.A = this;
    }
}

public class B
{
    public int BId { get; set; }
    public virtual A A { get; set; }
}

class Program
{
    static void Main()
    {
        using (var ctx = new MyContext(@"connection string"))
        {
            ctx.MyAs.Add(new A { Almost1 = 1, Almost2 = 1 });
            ctx.SaveChanges();
        }
    }
}

Es wirft einInvalidOperationException Sprichwort:

Die angegebenen Assoziations-Fremdschlüsselspalten 'Almost1, Almost2' sind ungültig. Die Anzahl der angegebenen Spalten muss mit der Anzahl der Primärschlüsselspalten übereinstimmen.

Wenn ich das ignoriereAId Spalte und stattdessen machenAlmost1 undAlmost2 ein zusammengesetzter Primärschlüssel, also meineOnModelCreating Methode sieht jetzt so aus:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    var aEntity = modelBuilder.Entity<A>();
    aEntity.ToTable("A");
    aEntity.HasKey(a => new { a.Almost1, a.Almost2 });
    aEntity.Ignore(a => a.AId);

    var bEntity = modelBuilder.Entity<B>();
    bEntity.ToTable("B");
    bEntity.HasKey(a => a.BId);
    bEntity
        .HasOptional(b => b.A)
        .WithMany(a => a.Bs)
        .Map(m => m.MapKey("Almost1", "Almost2"));
}

Es funktioniert, aber ich möchte das nicht wirklich tun, da es auch einen Tisch gibt (nennen wir esC) das bezieht sich aufA auf die traditionelle Art und Weise mit einemAId Spalte und der Fremdschlüssel geht abC.AId zuA.AId.

Ja, es ist ein bisschen seltsam, wie ich weiß - aber ist es möglich, in Entity Framework damit umzugehen?

Antworten auf die Frage(1)

Ihre Antwort auf die Frage