Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Ograniczenie wielokrotności naruszyło SQL Server 2008 - CodeFirst

Być może jesteś ofiarą konwencji mapowania EF Code-First, które automatycznie tworzą relację między NationAllies i toNation nie chcesz mieć.

Jeśli dobrze cię rozumiem (ale nie mam stuprocentowej pewności, jeśli tak), tak naprawdę chcesz mieć dwie relacje i odsłoniłeś tylko jeden koniec relacji w każdym z podmiotów. Tak więc NationAllies NIE wskazuje na toNation ale do "niewidzialnego" narodu właściciela w twoim NationAlly podmiot.

Jeśli tak jest, musisz jawnie nadpisać mapowania konwencji. W Fluent API EF 4.1 może to wyglądać tak:

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);
    }
}

To mapowanie utworzy dwa klucze obce OwnerID i NationID w NationAllies tabela, obie wskazują na klucz podstawowy ID w Nations tabela.

Edytuj

Oto aplikacja, z którą testowałem:

  • Utwórz nową aplikację konsolową w VS2010/.NET 4.0, nazwij ją „NationsApp”
  • Dodaj odniesienie do „EntityFramework.dll”
  • Wyczyść zawartość „Program.cs” i zamiast niej wklej następujący wpis:

Zawartość 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;
                }
            }
        }
    }
}

Możesz ustawić punkt przerwania na "throw", aby obserwować możliwe wyjątki w e w debugerze.

Tworzy to bazę danych o nazwie NationsApp.NationsContext jeśli używasz SQL Server Express i nie masz zdefiniowanych żadnych dalszych parametrów połączenia.

Daje dwie relacje Nation_NationAllies (FK to „OwnerID”) i NationAlly_toNation (FK to „NationID”). Wszystkie kolumny nie dopuszczają wartości null. Wynik w DB jest następujący:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Średnia ruchoma okna w serwerze sql

  2. Zapytanie SQL, które pobiera wszystkie kody pocztowe (adresy) w promieniu 20 mil od danego kodu pocztowego

  3. Zbiorcze wstawienie pliku CSV do SQL Server z niespójnymi cudzysłowami

  4. Jak przekonwertować uniksowy znacznik czasu na wartość daty/godziny w SQL Server

  5. Pakiet SSIS wykonany w agencie serwera nie wykonuje swojej pracy (nawet podczas raportowania sukcesu)