Entity Framework Core不支持映射到BigInteger数据类型。

8

我需要使用BigInteger类来处理大整数到我的类中,但是当尝试使用EntityFramework Core映射到DB表时,我收到以下错误:

AllianceRank.Reputation属性无法映射,因为它是BigInteger类型,它不是受支持的原始类型或有效的实体类型。要么显式地映射此属性,要么忽略它。

[Column("reputation")]
public BigInteger Reputation { get; set; }

看起来BigIntegers不是映射的支持类型。我该如何强制映射,或以其他方式解决此问题?

6个回答

5
如果你使用的是SQL Server,Entity Framework就必须对如何存储数据做出一些假设。例如,如果使用bigint,有可能出现值过大或过小的情况,这时候就不能再用bigint了。如果你真正意义上需要一个数字类型,而不是一个标识符,那么让EF将其查询为数字类型也会带来问题。因此,最好使用比较明确的类型,如longstring,以避免让EF猜测如何存储数据。

EF需要做出一些假设,但这些假设不会引发我上面发布的错误。这并不妨碍我使用longINT(3),尽管它无法存储,如果长整型足够大,就会在执行时抛出“越界”错误。将其移动到varchar并不能解决EF本身的问题,特别是因为我在查询中对列进行了数学运算。该错误意味着我可以明确地指示它映射到BigInteger,我该如何做到这一点? - Douglas Gaskell
你打算如何在SQL中表示BigInteger? - Chad Hedgcock
我现在在MySQL中将其表示为INT(25)。尽管long不支持那么大的数字,但目前它成功地映射到了long。只有当数字太大时,才会在映射时出现大整数的问题。 - Douglas Gaskell

4
自从EF Core 2.1起,您可以在DbContext类的OnModelCreating()函数中定义值转换(Value Conversions)来定义数据模型。最好的部分是,这允许属性值在读取或写入数据库时 自动转换!
因此,在您的情况下,如果C#中有一个BigInteger属性(Reputation),MySQL中对应的就是一个INT(25)字段,您可以这样设置:
var converter = new ValueConverter<BigInteger, long>(    
    model => (long)model,
    provider => new BigInteger(provider));

modelBuilder
    .Entity<AllianceRank>()
    .Property(e => e.Reputation)
    .HasConversion(converter);

顺带一提,你可能更希望使用可变长度的string 类型(比如 VARBINARY)在 MySQL 中存储该值,而不是使用 INT(25),因为 C# 中的 BigInteger 可以存储更大的值,因此在转换为 INT(25) 或 C# 的 long 时会引发异常。


1
这是正确的答案,谢谢! - Teoman shipahi

1
只支持标量类型、字符串和字节数组。 可用的最大标量类型是十进制数,它“仅”允许28-29个有效数字。

谢谢,不过我该如何解决这个问题呢?Entity Framework 肯定可以映射到类。我该如何明确指示它映射到 BigInteger? - Douglas Gaskell
你可以像这里讨论的那样进行显式映射。http://stackoverflow.com/questions/7505056/if-i-dont-explicitly-map-a-column-in-code-first-ef-to-an-existing-db-will-that。但是如果映射 big int,仍然会出现错误。 - Kalyan

0

使用

public long FieldName { get; set; }

在你的模型类中,它将是SQL中的bigint数据类型。

这与C#的BigInteger结构体无关。 - Gert Arnold

0
对于在类似情况下收到这个晦涩错误信息的可怜人们:
无法将类型为 'System.Int64' 的对象转换为类型 'System.Decimal'。
你可能会认为Entity Framework会自动将SQL Server的bigint(64位无符号整数)映射到相应的C# long(也是64位无符号整数),但实际上并不是这样...
所以,在你的DbContext的OnModelCreating(ModelBuilder modelbuilder)方法中,你需要提供一些指导,使用HasColumnType(),像这样:
using Microsoft.EntityFrameworkCore;

namespace Some.Namespace
{
    public class YourClassDbContext : DbContext
    {
        public YourClassDbContext(DbContextOptions<YourClassDbContext> options) : base(options) 
        {
        }

        public YourClassDbContext() {}

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            /* omitted stuff for PK and index */
            modelBuilder.Entity<ClassXYZ>().Property(t => t.Id).HasColumnType("long");
            
            base.OnModelCreating(modelBuilder);
        }
    

感谢上面@Kelvin Lai 的帮助,他的答案让我找到了正确的方向,以及https://learn.microsoft.com/en-us/ef/core/modeling/value-conversions

0

我的问题已经解决: 使用int64而不是biginteger

public class MyClassName
    {
        [Key]
        public Int64 TableId { get; set; }
    }

1
一个 Int64 是一个 long,而不是一个 BigInteger。这并不能解决问题,因为这违背了使用 BigInteger 的目的,即处理过大的数字,超出了 long 的范围。 - Douglas Gaskell
换句话说:解决你的问题,而不是问题本身。因此:不是答案。 - Gert Arnold
嗨。我使用了公共Int64 TableId { get; set; },并且通过EF Core创建了表:Sql数据库中的Bigint字段。 - mohammad javadi
那不是重点。问题是关于C#的BigInteger结构体。你的回答与此无关。顺便说一下,这个是相同的答案。 - Gert Arnold

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