Один ко многим в ядре Ef Fk Viloation - PullRequest
0 голосов
/ 11 июля 2020

Хорошо, я думаю, что я ошибся в построителе моделей. Мне нужен случай, который может быть одним случаем, но внутри этого одного случая может быть много отношений.

modelBuilder.Entity<RelationShips>()
              .HasOne<MISObject>(s => s.Case)
              .WithMany(g => g.RelationShip)
          .HasForeignKey(s => s.MisObjectId);

Но когда я пытаюсь сохранить с помощью приведенного выше

DbUpdateException: An произошла ошибка при обновлении записей. Подробнее см. Внутреннее исключение. SqlException: оператор INSERT конфликтует с ограничением FOREIGN KEY «FK_RelationShips_MISobject_MisObjectId». Конфликт произошел в базе данных «MISSystem», таблица «dbo.MISobject», столбец «Id». Оператор был прерван.

Мой MISObject имеет набор отношений как таковых

public class MISObject {
    public int Id { get; set; }
    public ICollection<RelationShips> RelationShip { get; set; }
}

public class RelationShips {
    public int Id { get; set; }        
    public MISObject Case { get; set; }
}

Будет ли вышеупомянутое не допускать отношения один ко многим, в основном в одном случае может быть 20 отношений но случаев могло быть много. Но эти 20 отношений должны принадлежать только к этому случаю, если это так.

Я думаю, мне нужно использовать hasmany, но не знаю, как в этом контексте. *

Думаю, это может быть то, что мне нужно, но я не уверен, насколько это законно.

modelBuilder.Entity<MISObject>()
 .HasMany(c => c.RelationShip);

modelBuilder.Entity<RelationShips>()
 .HasMany(c => c.PersonOfIntrests);

modelBuilder.Entity<POI>()
  .HasMany(c => c.PersonOfIntrestsPhotos)
  .WithOne(e => e.PersonOfIntrest);

Ответы [ 2 ]

0 голосов
/ 12 июля 2020

Чтобы эта работа работала с FluentAPI, вам необходимо полностью определить навигацию и использовать внешний ключ:

public class Relationship {
    public int Id { get; set; }        
    public int MisObjectId { get; set; } // <-- add foreign key ID
    
    public MisObject Case { get; set; }
}

public class Context : DbContext
{
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MisObject>()
            .HasMany(o => o.Relationships)
            .WithOne(r => r.Case) // <-- add other endpoint
            .HasForeignKey(r => r.MisObjectId); // <-- add FK property
    }
}

Вот полностью рабочий консольный проект, демонстрирующий следующие концепции:

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace IssueConsoleTemplate
{
    public class MisObject {
        public int Id { get; set; }
        
        public ICollection<Relationship> Relationships { get; set; }
    }

    public class Relationship {
        public int Id { get; set; }        
        public int MisObjectId { get; set; } // <-- add foreign key ID
        
        public MisObject Case { get; set; }
    }

    public class Context : DbContext
    {
        public DbSet<MisObject> MisObjects { get; set; }
        public DbSet<Relationship> Relationships { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .UseSqlServer(@"Data Source=.\MSSQL14;Integrated Security=SSPI;Initial Catalog=So62854210")
                .UseLoggerFactory(
                    LoggerFactory.Create(
                        b => b
                            .AddConsole()
                            .AddFilter(level => level >= LogLevel.Information)))
                .EnableSensitiveDataLogging()
                .EnableDetailedErrors();
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<MisObject>()
                .HasMany(o => o.Relationships)
                .WithOne(r => r.Case) // <-- add other endpoint
                .HasForeignKey(r => r.MisObjectId); // <-- add FK property

            // Technically not necessary, because this navigation has already been defined
            // in the previous line, but might be good practice anyway.
            modelBuilder.Entity<Relationship>()
                .HasOne(r => r.Case)
                .WithMany(o => o.Relationships)
                .HasForeignKey(r => r.MisObjectId);
        }
    }
    
    internal static class Program
    {
        private static void Main()
        {
            using (var context = new Context())
            {
                context.Database.EnsureDeleted();
                context.Database.EnsureCreated();

                var newMisObject = new MisObject();
                var newRelationships = new[]
                {
                    new Relationship {Case = newMisObject},
                    new Relationship {Case = newMisObject},
                    new Relationship {Case = newMisObject},
                };

                context.MisObjects.Add(newMisObject);
                context.Relationships.AddRange(newRelationships);
                context.SaveChanges();
            }

            using (var context = new Context())
            {
                var misObjects = context.MisObjects
                    .Include(o => o.Relationships)
                    .ToList();

                Debug.Assert(misObjects.Count == 1);
                Debug.Assert(misObjects[0].Relationships.Count == 3);
            }
        }
    }
}

По совпадению, поскольку свойства в этом примере соответствуют соглашениям об именах EF Core, вы можете даже полностью удалить метод OnModelCreating() здесь, и результат все равно будет работать. См. Relationships: Conventions для получения дополнительной информации об этом.

0 голосов
/ 12 июля 2020

Просто используйте соглашение, нет необходимости использовать свободную конфигурацию для отношений:

public class MISObject
    {
        public int Id { get; set; }
        public ICollection<RelationShips> RelationShip { get; set; }
    }
public class RelationShips
    {
        public int Id { get; set; }
        public int CaseId { get; set; }
        public MISObject Case { get; set; }
    }

без каких-либо ошибок, EF Core делает ваши таблицы в базе данных.

...