实体框架:如何检查列是否具有ConcurrencyCheck属性?

时间:2014-03-19 21:40:56

标签: c# entity-framework concurrency code-first

正如标题所说,有没有办法检查某列是否具有并发检查属性?

更确切地说,我试图将当前值与数据库值进行比较,我需要知道哪些列不同但忽略了并发检查列。验证类型不是一种选择,因为我使用的是并发检查不是byte[]的Oracle,而是一个由触发器更新的数字列,并映射到我班级的decimal

我发现here是获取列的方法,并检查哪些是/是主键,但看起来EdmScalarPropertyAttribute只知道EntityKeyIsNullable。那么我的问题是:有没有办法为ConcurencyCheck专栏做类似的事情?

提前谢谢。

2 个答案:

答案 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;
    }
}