如何更改Entity Framework 6中字符串属性的默认最大长度? [英] How can I change the default max length of string properties in Entity Framework 6?
问题描述
默认约定,实体模型中没有明确给出最大长度的字符串属性在数据库中设置为 nvarchar(max)
。我们希望覆盖这个约定,并给出字符串的最大长度 nvarchar(100)
,如果它们还没有被明确设置。
By default convention, strings properties in an entity model that are not explicitly given a max length are set to nvarchar(max)
in the database. We wish to override this convention and give strings a max length of nvarchar(100)
if they are not already explicitly set otherwise.
我发现了 PropertyMaxLengthConvention
内置的约定,其描述和文档似乎是我正在寻找的。但是,它不工作,或者我使用它错了,或者它不做我认为它。
I discovered the PropertyMaxLengthConvention
built-in convention, which by its description and documentation would seem to be what I am looking for. However, it either doesn't work or I'm using it wrong or it just doesn't do what I think it does.
我已经尝试只是添加约定:
I've tried simply adding the convention:
modelBuilder.Conventions.Add(new PropertyMaxLengthConvention(100));
然后我以为也许默认使用了,所以我尝试先删除它: p>
Then I thought maybe the default one is already being used, so I tried removing it first:
modelBuilder.Conventions.Remove<PropertyMaxLengthConvention>();
modelBuilder.Conventions.Add(new PropertyMaxLengthConvention(100));
我甚至尝试明确地在默认情况下添加约定:
I even tried explictly adding the convention before and after the default one:
modelBuilder.Conventions.AddBefore<PropertyMaxLengthConvention>(new PropertyMaxLengthConvention(100));
modelBuilder.Conventions.AddAfter<PropertyMaxLengthConvention>(new PropertyMaxLengthConvention(100));
没有喜悦。当我添加迁移时,列仍然创建为 nvarchar(max)
。
No joy. When I add migrations, the columns are still created as nvarchar(max)
.
有没有办法使用那个惯例做我想要的?如果没有,我可以编写一个自定义约定,将默认字符串属性设置为 nvarchar(100)
,但仍然允许我明确地将它们设置为不同的值,包括maxlength? p>
Is there a way to use that convention to do what I want? If not, can I write a custom convention that will default string properties to nvarchar(100)
but will still allow me to explicitly set them to a different value including maxlength?
推荐答案
在跟踪上述约定的源代码后,我发现它只设置指定的属性的默认最大长度具有固定长度。 (奇怪!)
After tracking down the source code for the aforementioned convention, I discovered that it only sets the default max length for properties that are specified to have fixed length. (Bizarre!)
所以我拿起源代码并修改它来创建我自己的约定。现在,具有未指定最大长度的字符串属性将具有默认的最大长度,而不是nvarchar(max)。唯一的缺点是,在 IsMaxLength()
配置被明确应用的时候似乎没有一种方法来检测。所以如果我有一个我想要创建为nvarchar(max)的列,我不能使用 IsMaxLength()
来实现。
So I took the source code and modified it to create my own convention. Now string properties with unspecified max length will have a default max length instead of being nvarchar(max). The only downside is there doesn't appear to be a way to detect when the IsMaxLength()
configuration is explicitly applied. So if I have a column that I do want to have created as nvarchar(max) I can't use IsMaxLength()
to do it.
为了解决这个问题,我为StringPropertyConfiguration创建了一个名为 ForceMaxLength()
的扩展方法,该方法使用配置属性HasMaxLength(int .MaxValue)
- 通常是无效的值,但我可以在我的习惯惯例中轻松测试。当我检测到它时,我只需将MaxLength设置为null,并将IsMaxLength设置为true,并使属性配置继续正常。
To address this, I created an extension method for StringPropertyConfiguration called ForceMaxLength()
that configures the property with HasMaxLength(int.MaxValue)
- ordinarily an invalid value, but one for which I can easily test in my custom convention. When I detect it, I simply set the MaxLength back to null and set the IsMaxLength to true and let the property configuration continue as normal.
以下是自定义约定: p>
Here's the custom convention:
using System;
using System.Collections.Generic;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace MyProject.CustomConventions
{
public class CustomPropertyMaxLengthConvention : IConceptualModelConvention<EntityType>, IConceptualModelConvention<ComplexType>
{
private const int DefaultLength = 128;
private readonly int length;
public CustomPropertyMaxLengthConvention()
: this(DefaultLength)
{
}
public CustomPropertyMaxLengthConvention(int length)
{
if (length <= 0)
{
throw new ArgumentOutOfRangeException("length", "Invalid Max Length Size");
}
this.length = length;
}
public virtual void Apply(EntityType item, DbModel model)
{
SetLength(item.DeclaredProperties);
}
public virtual void Apply(ComplexType item, DbModel model)
{
SetLength(item.Properties);
}
private void SetLength(IEnumerable<EdmProperty> properties)
{
foreach (EdmProperty current in properties)
{
if (current.IsPrimitiveType)
{
if (current.PrimitiveType == PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String))
{
SetStringDefaults(current);
}
if (current.PrimitiveType == PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Binary))
{
SetBinaryDefaults(current);
}
}
}
}
private void SetStringDefaults(EdmProperty property)
{
if (property.IsUnicode == null)
{
property.IsUnicode = true;
}
SetBinaryDefaults(property);
}
private void SetBinaryDefaults(EdmProperty property)
{
if (property.MaxLength == int.MaxValue)
{
property.MaxLength = null;
property.IsMaxLength = true;
}
else if (property.MaxLength == null || !property.IsMaxLength)
{
property.MaxLength = length;
}
}
}
}
这是扩展方法:
using System.Data.Entity.ModelConfiguration.Configuration;
namespace MyProject.Model.Mapping
{
public static class MappingExtensions
{
public static void ForceMaxLength(this StringPropertyConfiguration obj)
{
obj.HasMaxLength(int.MaxValue);
}
}
}
使用方法如下: / p>
Here's how it's used:
using System.Data.Entity.ModelConfiguration;
namespace MyProject.Model.Mapping
{
public class MyEntityMap : EntityTypeConfiguration<MyEntity>
{
public MyEntityMap()
{
Property(v => v.StringValue).ForceMaxLength();
}
}
}
这篇关于如何更改Entity Framework 6中字符串属性的默认最大长度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!