正如标题所说,有没有办法检查某列是否具有并发检查属性?
更确切地说,我试图将当前值与数据库值进行比较,我需要知道哪些列不同但忽略了并发检查列。验证类型不是一种选择,因为我使用的是并发检查不是byte[]
的Oracle,而是一个由触发器更新的数字列,并映射到我班级的decimal
。
我发现here是获取列的方法,并检查哪些是/是主键,但看起来EdmScalarPropertyAttribute
只知道EntityKey
和IsNullable
。那么我的问题是:有没有办法为ConcurencyCheck专栏做类似的事情?
提前谢谢。
答案 0 :(得分:1)
好的,我明白了:
var properties = from p in
(from x in typeof(User).GetProperties()
select new{Name = x.Name, Attributes = x.GetCustomAttributes(false)})
where p.Attributes.Any(t => t is ConcurrencyCheckAttribute)
select p;
我是这样写的,因为我也想要属性名称。删除where子句将提供所有属性及其自定义属性(包括列名称)。
答案 1 :(得分:0)
我有一个包含扩展方法的类,可以让我读取这样的数据注释:
int maxRefLen = ReflectionAPI.GetProperty<Organisation, String>(x => x.Name)
.GetAttribute<StringLengthAttribute>()
.GetValueOrDefault(x => x.MaximumLength, 256);
所以要检索ConcurrencyCheckAttribute
你应该能够这样做:
var attr = ReflectionAPI.GetProperty<User, String>(x => x.Name)
.GetAttribute<ConcurrencyCheckAttribute>();
这是ReflectionAPI类:
请注意,该课程包括@JonSkeet发布并描述为“邪恶”的黑客攻击的一部分。我个人认为这一点并不是那么糟糕,但你应该阅读以下参考资料:
Override a generic method for value types and reference types
Evil code - overload resolution workaround
public static class ReflectionAPI
{
public static int GetValueOrDefault<TInput>(this TInput a, Func<TInput, int> func, int defaultValue)
where TInput : Attribute
//Have to restrict to struct or you get the error:
//The type 'R' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable<T>'
{
if (a == null)
return defaultValue;
return func(a);
}
public static Nullable<TResult> GetValueOrDefault<TInput, TResult>(this TInput a, Func<TInput, TResult> func, Nullable<TResult> defaultValue)
where TInput : Attribute
where TResult : struct
//Have to restrict to struct or you get the error:
//The type 'R' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable<T>'
{
if (a == null)
return defaultValue;
return func(a);
}
//In order to constrain to a class without interfering with the overload that has a generic struct constraint
//we need to add a parameter to the signature that is a reference type restricted to a class
public class ClassConstraintHack<T> where T : class { }
//The hack means we have an unused parameter in the signature
//http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/evil-code-overload-resolution-workaround.aspx
public static TResult GetValueOrDefault<TInput, TResult>(this TInput a, Func<TInput, TResult> func, TResult defaultValue, ClassConstraintHack<TResult> ignored = default(ClassConstraintHack<TResult>))
where TInput : Attribute
where TResult : class
{
if (a == null)
return defaultValue;
return func(a);
}
//I don't go so far as to use the inheritance trick decribed in the evil code overload resolution blog,
//just create some overloads that take nullable types - and I will just keep adding overloads for other nullable type
public static bool? GetValueOrDefault<TInput>(this TInput a, Func<TInput, bool?> func, bool? defaultValue)
where TInput : Attribute
{
if (a == null)
return defaultValue;
return func(a);
}
public static int? GetValueOrDefault<TInput>(this TInput a, Func<TInput, int?> func, int? defaultValue)
where TInput : Attribute
{
if (a == null)
return defaultValue;
return func(a);
}
public static T GetAttribute<T>(this PropertyInfo p) where T : Attribute
{
if (p == null)
return null;
return p.GetCustomAttributes(false).OfType<T>().LastOrDefault();
}
public static PropertyInfo GetProperty<T, R>(Expression<Func<T, R>> expression)
{
if (expression == null)
return null;
MemberExpression memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
return null;
return memberExpression.Member as PropertyInfo;
}
}