sql >> Base de Datos >  >> RDS >> Sqlserver

La restricción de multiplicidad violó SQL Server 2008 - CodeFirst

Quizás sea víctima de las convenciones de mapeo EF Code-First que crean automáticamente una relación entre NationAllies y toNation no quieres tener.

Si te entiendo correctamente (pero no estoy 100 por ciento seguro, si lo hago), en realidad quieres tener dos relaciones y has expuesto solo un extremo de la relación en cada una de las entidades. Entonces, NationAllies NO apunta a toNation sino a una nación Propietaria "invisible" en su NationAlly entidad.

Si ese es el caso, debe sobrescribir explícitamente las asignaciones de convenciones. En la API fluida de EF 4.1, esto podría verse así:

public class MyContext : DbContext
{
    public DbSet<Nation> Nations { get; set; }
    public DbSet<NationAlly> NationAllies { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Nation>()
            .HasMany(n => n.NationAllies)
            .WithRequired()
            .Map(conf => conf.MapKey("OwnerID"))
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<NationAlly>()
            .HasRequired(a => a.toNation)
            .WithMany()
            .Map(conf => conf.MapKey("NationID"))
            .WillCascadeOnDelete(false);
    }
}

Esta asignación crearía las dos claves foráneas OwnerID y NationID en los NationAllies tabla, ambos apuntando a la clave principal ID en las Nations mesa.

Editar

Aquí está la aplicación con la que he probado:

  • Cree una nueva aplicación de consola en VS2010 / .NET 4.0, asígnele el nombre "NationsApp"
  • Agregue una referencia a "EntityFramework.dll"
  • Borrar el contenido de "Program.cs" y pegar en su lugar lo siguiente en:

Contenido de Program.cs:

using System;
using System.Collections.Generic;
using System.Data.Entity;

namespace NationsApp
{
    public class Nation
    {
        public int ID { get; set; }
        public int name { get; set; }
        public List<NationAlly> NationAllies { get; set; }
    }

    public class NationAlly
    {
        public int ID { get; set; }
        public int level { get; set; }
        public Nation toNation { get; set; }
    }

    public class NationsContext : DbContext
    {
        public DbSet<Nation> Nations { get; set; }
        public DbSet<NationAlly> NationAllies { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Nation>()
                .HasMany(n => n.NationAllies)
                .WithRequired()
                .Map(conf => conf.MapKey("OwnerID"))
                .WillCascadeOnDelete(false);

            modelBuilder.Entity<NationAlly>()
                .HasRequired(a => a.toNation)
                .WithMany()
                .Map(conf => conf.MapKey("NationID"))
                .WillCascadeOnDelete(false);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var context = new NationsContext())
            {
                try
                {
                    // We have three Nations and two Allies
                    Nation nation1 = new Nation() {
                        NationAllies = new List<NationAlly>() };
                    Nation nation2 = new Nation() {
                        NationAllies = new List<NationAlly>() };
                    Nation nation3 = new Nation() {
                        NationAllies = new List<NationAlly>() };
                    NationAlly ally1 = new NationAlly();
                    NationAlly ally2 = new NationAlly();

                    // Nation1 has two Allies
                    // (Nation1 is the "owner" of both Allies)
                    nation1.NationAllies.Add(ally1);
                    nation1.NationAllies.Add(ally2);

                    // toNation of ally1 refers to Nation2
                    ally1.toNation = nation2;
                    // toNation of ally2 refers to Nation3
                    ally2.toNation = nation3;

                    context.Nations.Add(nation1);
                    context.Nations.Add(nation2);
                    context.Nations.Add(nation3);

                    context.SaveChanges();
                }
                catch (Exception e)
                {
                    throw;
                }
            }
        }
    }
}

Puede establecer un punto de interrupción en "lanzar" para observar posibles excepciones en e en el depurador.

Esto crea una base de datos llamada NationsApp.NationsContext si está utilizando SQL Server Express y no tiene más cadenas de conexión definidas.

Da dos relaciones Nation_NationAllies (FK es "ID de propietario") y NationAlly_toNation (FK es "NationID"). Todas las columnas no aceptan valores NULL. El resultado en la BD es el siguiente: