简体   繁体   English

实体框架核心:具有与PK不同的DataType的FK

[英]Entity Framework Core: FK with Different DataType than PK

Runtime : netcoreapp2.0 运行时 :netcoreapp2.0

ASP.Net Core : 2.0.1 ASP.Net核心 :2.0.1

EF Core : 2.0.1 EF Core :2.0.1

Microsoft.EntityFrameworkCore.SqlServer : 2.0.1 Microsoft.EntityFrameworkCore.SqlServer :2.0.1

So, I'm working on an old database that is being used by lots of services and the original creators defined the PK of one table as short and a FK to that table as an int. 所以,我正在处理一个被许多服务使用的旧数据库,原始创建者将一个表的PK定义为short,将该表的FK定义为int。 Is it at all possible for me to handle this case? 我可以处理这个案子吗?

Note: it is not feasible to change the column type at this time. 注意:此时更改列类型是不可行的。

Consider the two classes: 考虑两个类:

public class Database {
  public short DatabaseId { get; set; }
  public Database { get; set; }
}

public class Client {
  public int ClientId { get; set; }
  public int DatabaseId { get; set; }
  public Database Database { get; set; }
}

My first attempt: 我的第一次尝试:

public int DatabaseId { get; set; }
[ForeignKey("DatabaseId")] public Database Database { get; set; }

throws

System.InvalidOperationException: The relationship from 'Client.Database' to 'Database.Client' with foreign key properties {'DatabaseId' : int} cannot target the primary key {'DatabaseId' : short} because it is not compatible. Configure a principal key or a set of compatible foreign key properties for this relationship.

Using the fluent API now: 现在使用流畅的API:

modelBuilder.Entity<Client>(table => {    
    table.HasOne(p => p.Database)
        .WithOne(i => i.Client)
        .HasForeignKey<Client>(c => c.DatabaseId)
        .HasPrincipalKey<Database>(d => d.DatabaseID);
});

Attempting to define a shadow property failed 尝试定义阴影属性失败

modelBuilder.Entity<Client>(table => {
    table.Property<int>("DatabaseId");

    table.HasOne(p => p.Database)
        .WithOne(i => i.Client)
        .HasForeignKey("DatabaseId")
        .HasPrincipalKey<Database>(d => d.DatabaseId);
});

throws

System.InvalidOperationException: You are configuring a relationship between 'Client' and 'Database' but have specified a foreign key on 'DatabaseId'. The foreign key must be defined on a type that is part of the relationship.

Okay, so no shadow properties this time: 好的,这次没有影子属性:

modelBuilder.Entity<Client>(table => {

    table.HasOne(p => p.Database)
        .WithOne(i => i.Client)
        .HasForeignKey<Client>(c => c.DatabaseId)
        .HasPrincipalKey<Database>(d => d.SQLDatabaseID);
});

throws

System.InvalidOperationException: The types of the properties specified for the foreign key {'DatabaseId'} on entity type 'Client' do not match the types of the properties in the principal key {'DatabaseID'} on entity type 'Database'.

So, then I tried just changing the entity type and maybe EF will be able to map int to int16. 所以,然后我尝试只更改实体类型,也许EF可以将int映射到int16。

public class Client {
  public int ClientId { get; set; }
  public short DatabaseId { get; set; } // <-- now a short
  public Database Database { get; set; }
}

throws

System.InvalidOperationException: An exception occurred while reading a database value for property 'Client.DatabaseId'. The expected type was 'System.Int16' but the actual value was of type 'System.Int32'. ---> System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.Int16'.

I'm starting to get the feeling this is not possible. 我开始觉得这是不可能的。

In EF Core 2.1 you can use value conversions, ie 在EF Core 2.1中,您可以使用值转换,即

entityBuilder.Property(c => c.Id).HasConversion<string>(); 

where the generic string is the database type and the destination is the model type. 其中通用字符串是数据库类型,目标是模型类型。 You can read further on https://docs.microsoft.com/es-es/ef/core/modeling/value-conversions 您可以在https://docs.microsoft.com/es-es/ef/core/modeling/value-conversions上进一步阅读

You can bypass error generated by entity framework by using the following code to define your foreign key 您可以使用以下代码来绕过实体框架生成的错误来定义外键

[Column(TypeName = "int")]
public short DatabaseId { get; set; }

but once you run migrations you will get this error and this is generated by sql server. 但是一旦你运行迁移,你将收到此错误,这是由sql server生成的。

Column 'Databases.DatabaseId' is not the same data type as referencing column 'Clients.DatabaseId' in foreign key 'FK_Clients_Databases_DatabaseId'. 列'Databases.DatabaseId'与外键'FK_Clients_Databases_DatabaseId'中引用列'Clients.DatabaseId'的数据类型不同。

And this makes perfect sense. 这很有道理。 What you are trying to achieve is not physically possible as SQL server requires foreign key to be same type otherwise you cannot build foreign key relationship. 您尝试实现的内容在物理上是不可能的,因为SQL Server要求外键是相同的类型,否则您无法构建外键关系。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM