Entity framework 如何动态地使实体属性为只读?

Entity framework 如何动态地使实体属性为只读?,entity-framework,data-annotations,dbcontext,Entity Framework,Data Annotations,Dbcontext,我正在使用EF4.5和DbContext。在业务规则层,我应该实现检查,以避免在某些实体场景中更改实体值属性。示例:StartProjecteDate仅当ProjectsStarted时才应为只读,但不应处于其他状态 我遵循原则,因此,我应该能够从上下文和UI检查只读属性列表 我的问题: 是否有可以将属性动态设置为只读的DataAnnotation验证程序? (如果没有,是否有其他/更好的解决方案?) 请注意,如果我使用的是Web表单(和Telerik)体系结构,则欢迎使用干净优雅的模式 我正试

我正在使用EF4.5和DbContext。在业务规则层,我应该实现检查,以避免在某些实体场景中更改实体值属性。示例:
StartProjecteDate
仅当
ProjectsStarted
时才应为只读,但不应处于其他状态

我遵循原则,因此,我应该能够从上下文和UI检查只读属性列表

我的问题:

是否有可以将属性动态设置为只读的DataAnnotation验证程序?

(如果没有,是否有其他/更好的解决方案?)

请注意,如果我使用的是Web表单(和Telerik)体系结构,则欢迎使用干净优雅的模式

我正试图在运行时设置和获取EditableAttribute,正如所解释的,但我无法从属性获取dataannotation属性,我的代码:

<EditableAttribute(False)>
<MaxLength(400, ErrorMessage:="Màxim 400 caracters")>
Public Property NomInvertebrat As String

公共属性NoInverteBrat为字符串


2013年11月8日编辑在挖掘文档之后,似乎DataAnotions是针对类的,而不是针对实例对象本身。也许iReadonlyableProperties接口可能是一种方法。

我有一个包含扩展方法的类,它允许我读取如下数据注释:

int maxRefLen = ReflectionAPI.GetProperty<Organisation, String>(x => x.Name)
                             .GetAttribute<StringLengthAttribute>()
                             .GetValueOrDefault(x => x.MaximumLength, 256);
bool isEditable = ReflectionAPI.GetProperty<Foo, String>(x => x.NomInvertebrat)
                               .GetAttribute<EditableAttribute>()
                               .GetValueOrDefault(x => x.AllowEdit, true);
<DisableEditAttribute(this.IsProjectStarted)>
Public Property NomInvertebrat As String

public override bool IsValid(bool value)
{
    bool result = true;
    // Add validation logic here.
    if(value)
    {
         //Compare Current Value Against DB Value.
    }
    return result;
}
至于在运行时设置数据注释,我自己还没有做过,但我读到这里有一个解决方案:

我认为获得一个特定类型的所有数据注释的列表是必要的。再说一次,我没试过这个

如果你把这些加在一起,我个人认为这感觉不是优雅而是笨拙,但是你已经要求使用
DataAnnotation
s解决方案,而更优雅的东西可能意味着进入你的架构

我倾向于这样做:

public bool StartDateIsReadOnly
{
   //use this property client-side to disable the input
   get{ return Project.IsStarted;}
}

//Implement IValidatable object to do server side validation
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext
{
   bool startdateIsChanged = // I'll leave you to work out this bit
   var results = new List<ValidationResult>();
   if(StartDateIsReadOnly && startdateIsChanged)
   results.Add(new ValidationResult("Start Date cannot be changed after project is started");
}
public bool StartDateIsReadOnly
{
//在客户端使用此属性可禁用输入
获取{return Project.IsStarted;}
}
//实现IValidatable对象以执行服务器端验证
公共IEnumerable验证(ValidationContext ValidationContext
{
bool startdatedischanged=//我会让你来解决这一点
var results=新列表();
如果(StartDateIsReadOnly&&startdateIsChanged)
添加(新的ValidationResult(“项目启动后不能更改开始日期”);
}
下面是ReflectionAPI类:

请注意,这个类包含了@JonSkeet发布并描述为“邪恶”的黑客的一部分。我个人认为这一点并不是那么糟糕,但你应该阅读以下参考资料:

公共静态类ReflectionAPI
{
公共静态int GetValuerDefault(此t输入a、Func Func、int defaultValue)
其中TInput:Attribute
//必须限制为struct,否则会出现错误:
//类型“R”必须是不可为null的值类型,才能将其用作泛型类型或方法“System.nullable”中的参数“T”
{
如果(a==null)
返回默认值;
返回函数(a);
}
公共静态可为Null的GetValuerDefault(此t输入a、Func Func、可为Null的defaultValue)
其中TInput:Attribute
其中TResult:struct
//必须限制为struct,否则会出现错误:
//类型“R”必须是不可为null的值类型,才能将其用作泛型类型或方法“System.nullable”中的参数“T”
{
如果(a==null)
返回默认值;
返回函数(a);
}
//为了在不干扰具有泛型结构约束的重载的情况下约束到类
//我们需要向签名添加一个参数,该参数是一个仅限于类的引用类型
公共类ClassConstraintHack其中T:class{}
//黑客意味着签名中有一个未使用的参数
//http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/evil-code-overload-resolution-workaround.aspx
公共静态TResult GetValueOrDefault(此t输入a,Func Func,TResult defaultValue,ClassConstraintHack忽略=默认值(ClassConstraintHack))
其中TInput:Attribute
结果:在哪里上课
{
如果(a==null)
返回默认值;
返回函数(a);
}
//我甚至没有使用邪恶代码重载解析博客中描述的继承技巧,
//只需创建一些接受可空类型的重载—我将继续为其他可空类型添加重载
public static bool?GetValueOrDefault(此t输入a、Func Func、bool?defaultValue)
其中TInput:Attribute
{
如果(a==null)
返回默认值;
返回函数(a);
}
公共静态int?GetValuerDefault(此t输入a、Func、int?defaultValue)
其中TInput:Attribute
{
如果(a==null)
返回默认值;
返回函数(a);
}
公共静态T GetAttribute(此属性信息为p),其中T:Attribute
{
if(p==null)
返回null;
返回p.GetCustomAttributes(false).OfType().LastOrDefault();
}
公共静态属性Info GetProperty(表达式)
{
if(表达式==null)
返回null;
MemberExpression MemberExpression=expression.Body作为MemberExpression;
if(memberExpression==null)
返回null;
返回memberExpression.Member作为PropertyInfo;
}
}

我有一个包含扩展方法的类,它允许我读取如下数据注释:

int maxRefLen = ReflectionAPI.GetProperty<Organisation, String>(x => x.Name)
                             .GetAttribute<StringLengthAttribute>()
                             .GetValueOrDefault(x => x.MaximumLength, 256);
bool isEditable = ReflectionAPI.GetProperty<Foo, String>(x => x.NomInvertebrat)
                               .GetAttribute<EditableAttribute>()
                               .GetValueOrDefault(x => x.AllowEdit, true);
<DisableEditAttribute(this.IsProjectStarted)>
Public Property NomInvertebrat As String

public override bool IsValid(bool value)
{
    bool result = true;
    // Add validation logic here.
    if(value)
    {
         //Compare Current Value Against DB Value.
    }
    return result;
}
至于在运行时设置数据注释,我自己还没有做过,但我读到这里有一个解决方案:

获取一个特定类型的所有数据注释的列表,我认为这是必要的。同样,我没有尝试过这样做

如果你把这些加在一起,我个人认为这感觉不是优雅而是笨拙,但是你已经要求使用
DataAnnotation
s解决方案,而更优雅的东西可能意味着进入你的架构