【问题标题】:Code First Entity Framework: Foreign key problemsCode First Entity Framework:外键问题
【发布时间】:2023-04-11 03:54:02
【问题描述】:

我正在尝试构建一个维持三向关系的系统。但是当我进入关系的第二个实例时,我遇到了异常。

这是基本代码

public class Role
{
    protected Role() { }

    public Role(string id, string description) : this()
    {
        Id = id;
        Description = description;
    }

    public string Id { get; set; }
    public string Description { get; set; }
}

public abstract class Entity
{
    public Guid EntityId { get; private set; }
}

public class Project : Entity
{
    protected Project()
    {
        UserProjectRoles = new Collection<UserProjectRole>();
    }

    public Project(string id, string description, string connectionString)
    {
        Id = id;
        Description = description;
        ConnectionString = connectionString;
    }

    public string Id { get; private set; }
    public string Description { get; private set; }
    public string ConnectionString { get; private set; }

    public virtual ICollection<UserProjectRole> UserProjectRoles { get; private set; }

    public IEnumerable<User> Users { get { return UserProjectRoles.Select(x => x.User).Distinct(); } }
}

public class User : Entity
{
    protected User()
    {
        UserProjectRoles = new Collection<UserProjectRole>();
    }

    public User(string uniqueName)
        : this()
    {
        UniqueName = uniqueName;
    }

    public string UniqueName { get; set; }

    public virtual ICollection<UserProjectRole> UserProjectRoles { get; private set; }

    public IEnumerable<Project> Projects { get { return UserProjectRoles.Select(x => x.Project).Distinct(); } }
}

public class UserProjectRole
{
    protected UserProjectRole() { }

    public UserProjectRole(Project project, User user, Role role)
    {
        Project = project;
        User = user;
        Role = role;
    }

    public Guid ProjectId { get; private set; }
    public Guid UserId { get; private set; }
    public string RoleId { get; private set; }

    public Project Project { get; private set; }
    public User User { get; private set; }
    public Role Role { get; private set; }
}

public class MasterContext : DbContext
{
    public MasterContext(string connectionString) : base(connectionString) { }

    public IDbSet<User> Users { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Entity>().HasKey(e => e.EntityId);
        modelBuilder.Entity<Entity>().Property(e => e.EntityId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<Project>().Map(u => u.MapInheritedProperties()).ToTable("Projects");
        modelBuilder.Entity<User>().Map(p => p.MapInheritedProperties()).ToTable("Users");

        modelBuilder.Entity<Role>().HasKey(r => r.Id);

        modelBuilder.Entity<UserProjectRole>().HasKey(x => new { x.ProjectId, x.UserId, x.RoleId });
        modelBuilder.Entity<UserProjectRole>().HasRequired(x => x.User).WithMany(u => u.UserProjectRoles).HasForeignKey(x => x.UserId).WillCascadeOnDelete(false);
        modelBuilder.Entity<UserProjectRole>().HasRequired(x => x.Project).WithMany(p => p.UserProjectRoles).HasForeignKey(x => x.ProjectId).WillCascadeOnDelete(false);
        modelBuilder.Entity<UserProjectRole>().HasRequired(x => x.Role).WithMany().HasForeignKey(x => x.RoleId).WillCascadeOnDelete(false);
    }
}

这是一个演示错误的测试用例。

[TestFixture]
public class EFTest
{
    private const string MasterConnectionString =
        "Data Source=localhost;Initial Catalog=TheDatabase;Integrated Security=True;";

    private static readonly Role DataCollector = new Role("1", "Data Collector");
    private static readonly Role Manager = new Role("2", "Manager");

    [Test]
    public void TheTest()
    {

        var user = new User("Tim the Enchanter");
        var project = new Project("Foo", "Bar", "Another Connection string");

        Database.SetInitializer(new DropCreateDatabaseAlways<MasterContext>());
        using (var masterContext = new MasterContext(MasterConnectionString))
        {
            user.UserProjectRoles.Add(new UserProjectRole(project, user, DataCollector));
            masterContext.Users.Add(user);
            masterContext.SaveChanges();
        }

        Database.SetInitializer(new CreateDatabaseIfNotExists<MasterContext>());
        using (var masterContext = new MasterContext(MasterConnectionString))
        {
            var u = masterContext.Users.First();
            var p = u.Projects.First();
            u.UserProjectRoles.Add(new UserProjectRole(p, u, Manager));

            masterContext.SaveChanges();
        }
    }
}

当我运行该测试时,我收到以下错误:

System.Data.Entity.Infrastructure.DbUpdateException:一个错误 更新条目时发生。请参阅内部异常 细节。 ----> System.Data.UpdateException : 发生错误时 更新条目。有关详细信息,请参阅内部异常。 ----> System.Data.SqlClient.SqlException:INSERT 语句冲突 带有 FOREIGN KEY 约束 “FK_dbo.UserProjectRoles_dbo.Projects_ProjectId”。冲突 发生在数据库“Dev_Local_Master”、表“dbo.Projects”、列中 '实体 ID'。声明已终止。

【问题讨论】:

  • 你在哪一行得到错误?
  • 第二次 SaveChanges() 调用抛出异常。
  • 去掉modelBuilder.Entity&lt;Entity&gt;()的两行,通过数据注解配置Entity会怎样? (效果是 Entity 不为 EF 模型所知)。
  • 我特别避免使用数据注释。我不希望业务 POCO 对象知道持久层。
  • 我明白了。这只是为了尝试,因为我注意到具有基本类型的 EF 模型通常最好不知道基本类型,只知道派生类型。数据注释是实现这一目标的快速方法。如果它有帮助,应该会有一个 way to do it without data annotations,但这需要更多的工作。

标签: ef-code-first entity-framework-5


【解决方案1】:

事实证明,UserProjectRole 上的用户、项目和角色都需要是虚拟的才能正常工作。

错误消息在解决这个问题时帮助不大。

【讨论】:

    猜你喜欢
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    • 2015-06-25
    • 2015-09-18
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    相关资源
    最近更新 更多