JC *_*ord 2 ef-code-first entity-framework-6.1
默认情况下,实体模型中未明确指定最大长度的字符串属性在nvarchar(max)数据库中设置为。我们希望覆盖这个约定并给字符串一个最大长度,nvarchar(100)如果它们还没有明确设置的话。
我发现了PropertyMaxLengthConvention内置约定,根据其描述和文档,这似乎是我正在寻找的。但是,它要么不起作用,要么我用错了它,要么就是它没有做我认为的那样。
我试过简单地添加约定:
modelBuilder.Conventions.Add(new PropertyMaxLengthConvention(100));
Run Code Online (Sandbox Code Playgroud)
然后我想也许默认的已经被使用了,所以我先尝试删除它:
modelBuilder.Conventions.Remove<PropertyMaxLengthConvention>();
modelBuilder.Conventions.Add(new PropertyMaxLengthConvention(100));
Run Code Online (Sandbox Code Playgroud)
我什至尝试在默认约定之前和之后显式添加约定:
modelBuilder.Conventions.AddBefore<PropertyMaxLengthConvention>(new PropertyMaxLengthConvention(100));
modelBuilder.Conventions.AddAfter<PropertyMaxLengthConvention>(new PropertyMaxLengthConvention(100));
Run Code Online (Sandbox Code Playgroud)
没有喜悦。当我添加迁移时,列仍然创建为nvarchar(max).
有没有办法使用该约定来做我想做的事?如果没有,我是否可以编写一个自定义约定,将默认字符串属性设置为nvarchar(100)但仍允许我将它们显式设置为不同的值,包括 maxlength?
在跟踪上述约定的源代码后,我发现它只为指定为固定长度的属性设置默认最大长度。(奇怪!)
所以我拿了源代码并修改它以创建我自己的约定。现在,未指定最大长度的字符串属性将具有默认的最大长度,而不是 nvarchar(max)。唯一的缺点是似乎没有一种方法可以检测何时IsMaxLength()明确应用配置。因此,如果我有一个我确实想创建为 nvarchar(max) 的列,我将无法使用IsMaxLength()它。
为了解决这个问题,我为 StringPropertyConfiguration 创建了一个扩展方法,称为ForceMaxLength()该方法配置属性HasMaxLength(int.MaxValue)- 通常是一个无效值,但我可以在我的自定义约定中轻松测试该值。当我检测到它时,我只需将 MaxLength 设置回 null 并将 IsMaxLength 设置为 true 并让属性配置正常继续。
这是自定义约定:
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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是扩展方法:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是它的使用方法:
using System.Data.Entity.ModelConfiguration;
namespace MyProject.Model.Mapping
{
public class MyEntityMap : EntityTypeConfiguration<MyEntity>
{
public MyEntityMap()
{
Property(v => v.StringValue).ForceMaxLength();
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3762 次 |
| 最近记录: |