在使用ASP.NET MVC 3和Entity Framework 4.1 Code First将图像存储到SQL CE 4.0时出现错误。

19

我想将一张图片保存到SQL Compact Edition (CE) 数据库中。

在我的学生模型中,我声明了该字段为:

[Column(TypeName = "image")]
public byte[] Photo { get; set; }

数据库中创建了一个包含图像数据类型的"Photo"列,如下图所示:

enter image description here

问题是:

当我运行应用程序并尝试保存一个大小为3 MB的学生照片时,会出现异常:

validationError.ErrorMessage = "The field Photo must be a string or array type
with a maximum length of '4000'."

SQL Server CE支持这些数据类型。在这篇SQL Express和SQL Compact Edition(CE)的比较中,我们得知SQL CE通过使用image数据类型支持二进制(BLOB)存储。

Image = 变长二进制数据,最大长度为2^30-1(1,073,741,823)字节。存储是值的字节长度。

我认为Image可以胜任这个任务。

我做错了什么?这是一个bug吗?

注意:

我还尝试了MaxLength数据注释:

[Column(TypeName = "image")]
[MaxLength(int.MaxValue)]
public byte[] Photo { get; set; } 

但我遇到了这个异常:

Binary column with MaxLength greater than 8000 is not supported.

编辑:

我找到了关于EF 4.1发布的文章,其中提到:

 

更改非主键字符串和二进制列的默认长度从“128”到“Max”。当使用SQL Compact时,不支持“Max”列。在针对SQL Compact运行时,另一个Code First约定将设置默认长度为4000。有关此更改的更多详细信息包含在最近的博客文章中(链接如下)。

好吧好吧......我能让它正常工作的唯一方法是按照这里所述的做法设置DbContext.Configuration.ValidateOnSaveEnabled = false。这是一个解决方法,正如文章所建议的那样。

3个回答

19

对于遇到这个问题的人,Erik Ejlskov Jensen发布了一个可工作的控制台应用程序,演示了解决此错误的方法。正如OP所指出的那样,答案的关键部分是:

    public StudentContext()
    {
        // Required to prevent bug - https://dev59.com/W2025IYBdhLWcg3w4qIx
        this.Configuration.ValidateOnSaveEnabled = false;        
    }

已经找到了更好的解决方案。不要禁用验证。 [来自博客文章的更新] 更新:来自LINQ to SQL和EF Code First的知名人士@DamienGuard指出,更好且更独立于提供程序的解决方案是使用MaxLength而不是TypeName="ntext"。

更新2:使用[MaxLength]可以防止任何验证错误,无需禁用验证。


1
感谢您让我知道他的博客文章。当我遇到这个错误时,我联系了Erik以便他能进一步调查。看到有一个专门讨论这个问题的博客文章是很好的。正如我的问题所提到的那样,解决这个问题的唯一方法是设置ValidateOnSaveEnabled = false - Leniel Maccaferri
我建议不要禁用验证。提到设置MaxLength的答案是更好的答案。 - Robin Caron
1
实际上,正确的答案是使用[MaxLength]属性,我已经相应地更新了我的博客文章。 - ErikEJ
1
我也遇到了类似的情况,但是无法使其工作。我正在使用EF 6和SQLCE 4的流畅API:modelBuilder.ComplexType().Property(data => data.Content).HasColumnType("image");我在Visual Studio的服务器资源管理器中进行了检查,并且在数据库中生成的列具有DataType=Image和Length=1073741823,但保存失败并出现与问题相同的错误。添加Configuration.ValidateOnSaveEnabled = false;也没有帮助。你还有什么提示吗? - Paul

13

使用MaxLength数据注释来指定没有最大长度的方法是不提供最大值。例如:

[MaxLength]
public byte[] Photo { get; set; }

SQL Compact提供程序将属性映射到"image",EF验证将识别未指定最大长度,因此无需禁用。如果您想明确地映射到"image"列,则可以这样做:

[Column(TypeName = "image")]
[MaxLength]
public byte[] Photo { get; set; }

使用 SQL Compact 时将产生相同的结果。


2
正是我所需要的,同时将 [MaxLength] 应用于字符串会在 SQL Server CE 中创建 ntext(无限长度)列。 - Tom Carver
如果只使用[MaxLength],会出现“不支持默认值”的异常。而且如果使用[MaxLength(n)],n的值不能大于8000? - smerlung
发生在 Microsoft SQL Azure (RTM) - 12 中。解决方案是 [Column(TypeName = "image"),MaxLength]。 - none

3
我知道这可能有点晚了,但它可以使其他程序员受益。
您可以在OnModelCreating(DbModelBuilder modelBuilder)方法内部添加context类。
 modelBuilder.Entity<EntityName>().Property(p => p.Photo).IsMaxLength();

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