2014-05-15 1 views
2

기본적으로 최대 길이가 명시 적으로 지정되지 않은 엔터티 모델의 문자열 속성은 데이터베이스에서 nvarchar(max)으로 설정됩니다. 이 규칙을 무시하고 문자열에 최대 길이가 nvarchar(100) 인 경우 명시 적으로 다르게 설정하지 않은 경우 문자열을 제공하고자합니다.Entity Framework 6에서 문자열 속성의 기본 최대 길이를 어떻게 변경합니까?

나는 설명과 문서를 통해 내가 찾고있는 것으로 보이는 기본 제공 규칙 인 PropertyMaxLengthConvention을 발견했습니다. 그러나, 그것도 작동하지 않거나 내가 잘못 사용하고 있거나 그냥 내가 생각하는대로하지 않습니다.

나는 단순히 규칙을 추가하는 시도했습니다

다음
modelBuilder.Conventions.Add(new PropertyMaxLengthConvention(100)); 

나는 어쩌면 디폴트가 이미 사용하고있는 생각, 그래서 내가 먼저 제거 시도 :

modelBuilder.Conventions.Remove<PropertyMaxLengthConvention>(); 
modelBuilder.Conventions.Add(new PropertyMaxLengthConvention(100)); 

심지어 명시 적으로 시도 기본 전후에 규칙을 추가하십시오.

modelBuilder.Conventions.AddBefore<PropertyMaxLengthConvention>(new PropertyMaxLengthConvention(100)); 
modelBuilder.Conventions.AddAfter<PropertyMaxLengthConvention>(new PropertyMaxLengthConvention(100)); 

기쁨. 마이그레이션을 추가하면 열은 여전히 ​​nvarchar(max)으로 생성됩니다.

내가 원하는 것을하기 위해 그 대회를 사용할 방법이 있습니까? 그렇지 않다면 기본 문자열 속성이 nvarchar(100) 인 사용자 정의 규칙을 작성할 수 있지만 maxlength를 포함하여 다른 값으로 명시 적으로 설정할 수 있습니까?

답변

4

위의 규칙에 대한 소스 코드를 추적 한 결과, 고정 길이로 지정된 속성의 기본 최대 길이 만 설정한다는 것을 발견했습니다. (기괴한!)

그래서 소스 코드를 가져 와서 내 자신의 규칙을 만들었습니다. 이제 최대 길이가 지정되지 않은 문자열 속성은 nvarchar (max)가 아닌 기본 최대 길이를 갖습니다. 단 한 가지 단점은 구성이 명시 적으로 적용될 때를 감지하는 방법으로 보이지 않는다는 것입니다. 따라서 열을 nvarchar (max)로 만들려는 경우 IsMaxLength()을 사용할 수 없습니다. 하는 내가 쉽게 내 사용자 지정 규칙에 테스트 할 수 있습니다 일반적으로 잘못된 값,하지만 한 -

는이 문제를 해결하기 위해, 나는 StringPropertyConfiguration이 HasMaxLength(int.MaxValue)와 속성을 구성 ForceMaxLength() 전화에 대한 확장 메서드를 만들었습니다. 이를 감지하면 MaxLength를 다시 null로 설정하고 IsMaxLength를 true로 설정하고 속성 구성을 정상적으로 계속하도록합니다.

다음
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); 
     } 
    } 
} 

그것이 사용되는 방법은 다음과 같습니다 :

using System.Data.Entity.ModelConfiguration; 

namespace MyProject.Model.Mapping 
{ 
    public class MyEntityMap : EntityTypeConfiguration<MyEntity> 
    { 
     public MyEntityMap() 
     { 
      Property(v => v.StringValue).ForceMaxLength(); 
     } 
    } 
} 
2

하거나

public class StringConventions : Convention 
{ 
    public StringConventions() 
    { 
     this.Properties<string>().Configure(x => x.HasMaxLength(100)); 
    } 
} 
여기
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; 
      } 

     } 
    } 
} 

이 확장 방법이다 : 여기

사용자 정의 협약
0

EF6에서는 사용자 지정 코드 첫 번째 규칙을 사용할 수 있지만 nvarchar (max) 데이터 형식을 문자열 속성으로 지정하는 방법이 필요합니다. 그래서, 나는 다음과 같은 해결책을 찾았다.

/// <summary> 
/// Set this attribute to string property to have nvarchar(max) type for db table column. 
/// </summary> 
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 
public sealed class TextAttribute : Attribute 
{ 
} 

/// <summary> 
/// Changes all string properties without System.ComponentModel.DataAnnotations.StringLength or 
/// Text attributes to use string length 16 (i.e nvarchar(16) instead of nvarchar(max) by default). 
/// Use TextAttribute to a property to have nvarchar(max) data type. 
/// </summary> 
public class StringLength16Convention : Convention 
{ 
    public StringLength16Convention() 
    { 
     Properties<string>() 
      .Where(p => !p.GetCustomAttributes(false).OfType<DatabaseGeneratedAttribute>().Any()) 
      .Configure(p => p.HasMaxLength(16)); 

     Properties() 
      .Where(p => p.GetCustomAttributes(false).OfType<TextAttribute>().Any()) 
      .Configure(p => p.IsMaxLength()); 
    } 
} 

public class CoreContext : DbContext, ICoreContext 
{ 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     //Change string length default behavior. 
     modelBuilder.Conventions.Add(new StringLength16Convention()); 
    } 
} 


public class LogMessage 
{ 
    [Key] 
    public Guid Id { get; set; } 


    [StringLength(25)] // Explicit data length. Result data type is nvarchar(25) 
    public string Computer { get; set; } 

    //[StringLength(25)] // Implicit data length. Result data type is nvarchar(16) 
    public string AgencyName { get; set; } 

    [Text] // Explicit max data length. Result data type is nvarchar(max) 
    public string Message { get; set; } 
}