简体   繁体   中英

Entity framework : how to check if column has the ConcurrencyCheck attribute?

As the title says, is there a way to check if a certain column has the concurrency check attribute or not?

To be more precisely, I am trying to compare current values with database values and I need to know which columns are different but ignoring the concurrency check column. Verifying the type is not an option because I use Oracle where the concurrency check is not byte[] but is a numeric column updated by trigger and mapped to decimal in my class.

I found here a way to get the columns and check which are/is primary key, but it looks like EdmScalarPropertyAttribute only knows about EntityKey and IsNullable . So my question again: is there a way to do a similar thing for ConcurencyCheck column?

Thank you in advance.

Ok, I got it:

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;

I wrote it like this because I also want the property name. Removing the where clause will give all properties and their custom attributes (including column name).

I have a class containing extension methods that lets me read data annotations like this:

int maxRefLen = ReflectionAPI.GetProperty<Organisation, String>(x => x.Name)
                             .GetAttribute<StringLengthAttribute>()
                             .GetValueOrDefault(x => x.MaximumLength, 256);

So to retrieve the ConcurrencyCheckAttribute you should be able to do it like this:

var attr = ReflectionAPI.GetProperty<User, String>(x => x.Name)
                        .GetAttribute<ConcurrencyCheckAttribute>();

Here is the ReflectionAPI class:

Please note that the class includes part of a hack that @JonSkeet posted and described as "evil". I personally think this bit ain't so bad, but you should read the following references:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM