Ef核心Fk Viloation中的一对多

时间:2020-07-11 20:26:08

标签: c# entity-framework-core ef-core-3.0

好吧,我想我可能在模型构建器中有这个错误。我希望这种情况可以是一种情况,但是在一种情况下,它们可以有很多关系。

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

但是当我尝试保存以上内容

DbUpdateException:更新条目时发生错误。看到 内部异常的详细信息。 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,但不能确定在这种情况下如何使用。

编辑2

我认为这可能是我所需要的,但我不确定这是合法的。

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 :(得分:0)

要使用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

答案 1 :(得分:-1)

只需使用约定,就无需对关系使用流利的配置:

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使您的表在数据库中。