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