简体   繁体   中英

Entity Framework Generic Lookup based on Type

I have a database with a number of tables which are purely read only lookups. They're all 2 columns: Id & Description of the same type.

I want to create a generic method that takes the DbSet Type as T and returns from the appropriate table into a standard LookupModel class.

Here's what I've got:

    public List<LookupModel> GetLookupList<T>() where T : DbSet
    {
        try
        {
            using (var context = new TwoCEntities())
            {
                var rows = context.Set<T>();
                return rows.Select(row => new LookupModel
                {
                    Id = (int)row.GetType().GetProperty("Id").GetValue(row, null),
                    Description = row.GetType().GetProperty("Description").GetValue(row, null).ToString()
                }).ToList();
            }
        }
        catch (Exception e)
        {
            if (log.IsErrorEnabled) log.ErrorFormat("GetLookupList<{0}> raised exception {1} with message {2}", typeof(T), e.GetType(), e.Message);
            throw;
        }
    }

My problem is calling it. This does not compile:

var result =  lookupRepository.GetLookupList<DbSet<BedType>>();

I get this error

The type 'System.Data.Entity.DbSet<Repository.BedType>' cannot be used as type parameter 'T' in the generic type or method 'ILookupRepository.GetLookupList<T>()'. There is no implicit reference conversion from 'System.Data.Entity.DbSet<Repository.BedType>' to 'System.Data.Entity.DbSet'.

BedType is defined in my context as

public virtual DbSet<BedType> BedType { get; set; }

Could someone suggest where I've gone wrong?

The code that you have provided is nesting the DbSet .

What you have shown is resolving T to this:

context.Set<DbSet<BedType>>();

Your T needs to be a plain entity class. Remove the DbSet generic constraint on the GetLookup method and add the class one.

public List<LookupModel> GetLookupList<T>() where T : class
{
    try
    {
        using (var context = new TwoCEntities())
        {
            var rows = context.Set<T>();
            return rows.Select(row => new LookupModel
            {
                Id = (int)row.GetType().GetProperty("Id").GetValue(row, null),
                Description = row.GetType().GetProperty("Description").GetValue(row, null).ToString()
            }).ToList();
        }
    }
    catch (Exception e)
    {
        if (log.IsErrorEnabled) log.ErrorFormat("GetLookupList<{0}> raised exception {1} with message {2}", typeof(T), e.GetType(), e.Message);
        throw;
    }
}

This will have your type variable T resolve to the following within the method.

context.Set<BedType>();

When you call it use it like this:

var result = lookupRepository.GetLookupList<BedType>();

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