EF Core:数据库优先转换:外键错误列

3
我正在尝试通过将我的现有应用程序从 .net 4.6.2 with EF6 迁移到 .net Core 2.2 with EF Core 来学习asp.net core。 鉴于我有一个现有的数据库,我从数据库生成了模型以便开始移植。我的所有列名都使用下划线,并且在外键所在的地方,它们都以表名开头。 但是,在使用EF Core时,它坚持要求我的代码列名称更改为ManagerUserLoginId而不是Manager_UserLogin_ID,这很好,我可以浏览我的代码。 问题出现在当我尝试使用include查询UserLogin和Manager时。
__DB.UserLogin.Include(x=>x.Manager).First();

此次查询尝试在Manager查询中包括一个UserLoginId列以及Manager_UserLogin_ID列。

以下是相关类:

public partial class Manager
{
    public int ManagerId { get; set; }
    public int ManagerCompanyId { get; set; }
    public int ManagerUserLoginId { get; set; }
    public virtual Company ManagerCompany { get; set; }
    public virtual UserLogin ManagerUserLogin { get; set; }
}

public partial class UserLogin
{
    public UserLogin()
    {
        Manager = new HashSet<Manager>();
    }

    public int UserLoginId { get; set; }
    public string FullName { get; set; }

    public virtual ICollection<Manager> Manager { get; set; }
}

public partial class Company
{
    public Company()
    {
        Manager = new HashSet<Manager>();
    }

    public int CompanyId { get; set; }
    public string CompanyName { get; set; }

    public virtual ICollection<Manager> Manager { get; set; }
}

EF Core上下文具有以下功能:
protected override void OnModelCreating(ModelBuilder modelBuilder
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<Company>(entity =>
    {
        entity.HasKey(e => e.CompanyId).HasName("PK_Company_ID");
        entity.Property(e => e.CompanyId).HasColumnName("Company_ID");

        entity.Property(e => e.CompanyName)
            .IsRequired()
            .HasColumnName("Company_Name")
            .HasMaxLength(200);

    modelBuilder.Entity<Manager>(entity =>
    {
        entity.HasKey(e => e.ManagerId)
            .HasName("PK_Manager_ID")
            .ForSqlServerIsClustered(false);

        entity.HasIndex(e => new { e.ManagerCompanyId, e.ManagerUserLoginId })
            .HasName("IX_Manager")
            .IsUnique()
            .ForSqlServerIsClustered();

        entity.Property(e => e.ManagerId).HasColumnName("Manager_ID");

        entity.Property(e => e.ManagerCompanyId).HasColumnName("Manager_Company_ID");

        entity.Property(e => e.ManagerUserLoginId).HasColumnName("Manager_UserLogin_ID");

        entity.HasOne(d => d.ManagerCompany)
            .WithMany(p => p.Manager)
            .HasForeignKey(d => d.ManagerCompanyId)
            .OnDelete(DeleteBehavior.ClientSetNull)
            .HasConstraintName("FK_Manager_Company_ID");

        entity.HasOne(d => d.ManagerUserLogin)
            .WithMany(p => p.Manager)
            .HasForeignKey(d => d.ManagerUserLoginId)
            .OnDelete(DeleteBehavior.ClientSetNull)
            .HasConstraintName("FK_Manager_UserLogin_ID");
        });

    modelBuilder.Entity<UserLogin>(entity =>
    {
        entity.HasKey(e => e.UserLoginId).HasName("PK_UserLogin_ID");
        entity.HasIndex(e => e.UserLoginUid)
            .HasName("IX_UserLogin_UID")
            .IsUnique();

        entity.Property(e => e.UserLoginId).HasColumnName("UserLogin_ID");

        entity.Property(e => e.FullName)
            .IsRequired()
            .HasColumnName("Full_Name")
            .HasMaxLength(300);

        entity.Property(e => e.UserLoginUid).HasColumnName("UserLogin_UID");
    });

这是来自Sql Profiler的查询语句:



    exec sp_executesql N'SELECT [x.Manager].[Manager_ID], [x.Manager].[Manager_Company_ID], [x.Manager].[Manager_UserLogin_ID], , [x.Manager].[UserLoginId]
    FROM [Manager] AS [x.Manager]
    INNER JOIN (
        SELECT TOP(1) [x0].[UserLogin_ID]
        FROM [UserLogin] AS [x0]
        WHERE [x0].[UserLogin_UID] = @____UID_0
        ORDER BY [x0].[UserLogin_ID]
    ) AS [t] ON [x.Manager].[Manager_UserLogin_ID] = [t].[UserLogin_ID]
    ORDER BY [t].[UserLogin_ID]',N'@____UID_0 uniqueidentifier',@____UID_0='F55C9BBB-C7FF-4C87-B834-B2FE6B0F0B17'

请问有人可以帮我诊断和解决这个问题吗?


这可能会对您有所帮助 https://andrewlock.net/customising-asp-net-core-identity-ef-core-naming-conventions-for-postgresql/ - Maximilian Ast
谢谢您的文章,但它并没有回答我为什么我的代码会创建一个包含末尾列的查询的问题。我以用户和管理者表为例,我指的是整个数据库和所有查询。 - Stephen Calvert
你能给我展示一下你的管理器和用户类吗?顺便说一句,我从未尝试过使用现有数据库的CodeFirst,但是CodeFirst实际上可以很好地处理像User_Id这样的外键。 - Joshit
代码是通过VS命令行生成的。我已经添加了用户、公司和经理类。 - Stephen Calvert
这是整个配置吗?例如,Manager配置(modelBuilder)具有ManagerUserLoginId,但该类中没有该属性..? - Joshit
我正在尝试发布一个修改实际代码的示例。我的用户表实际上是UserLogin。 - Stephen Calvert
1个回答

0

昨天我尝试了几件事情,我对更改propertyNames感到满意:

public int ManagerUserLoginId { get; set; }更改为public int Manager_UserLogin_Id { get; set; }并从modelBuilder中删除entity.Property(e => e.Manager_UserLogin_Id).HasColumnName("Manager_UserLogin_ID");

这是一个快速修复...背后的问题似乎是一个更大的问题。我会创建一个与VS为您创建的相同配置/类的新数据库。

  • 创建一个新项目
  • 添加一个连接字符串和一个新的DB名称
  • 粘贴你的类
  • 创建一个新的DbContext
  • 进入包管理器控制台并粘贴add-migration InitialMigration

Ef Core将创建一个迁移来创建一个新的数据库,基于您的模型和配置。 注意:确保您的connectionString不指向任何现有的数据库。如果您执行迁移,您将失去任何现有数据库中的数据!

  • 如果您绝对确定指向一个新的DB,请粘贴update-database

此后,您可以插入新数据到您的TestDB中检查问题所在。


你想要我的实际代码而不是我犯错的那个吗? - Stephen Calvert
我不明白你的问题。为了给你所需的答案,我需要引起问题的完整代码...?用户和用户登录是两个不同的实体吗? - Joshit
我已经更新了问题,使用的是解决方案中的代码,而不是我尝试使用的示例代码。 - Stephen Calvert
我在模型中添加了HasKey元素,因为它们并未被工具创建,但查询仍然保持不变。 - Stephen Calvert
看起来要放弃这么多辛苦的工作并开始一个新项目真是太可惜了。微软的EF Core不够灵活确实令人遗憾。 - Stephen Calvert
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接