Zach M.
Zach M.

Reputation: 1194

Casting a generic entity using reflection with generic method

I have a method called RevertChanges which looks like the following:

public static void RevertChanges<TEntity>()
{
            var jsonData = DataAccess.GetEnvironmentJson((int)Environments.Production);
            var model = JsonConvert.DeserializeObject<Models.FullDataSetModel>(jsonData);
            var targetEntity = typeof(TEntity).Name;
            using (var db = new LoginPageContentEntities())
            {
                db.Database.ExecuteSqlCommand(String.Format("TRUNCATE TABLE [{0}]", targetEntity));
                var modelValue = model.GetType().GetProperty(targetEntity).GetValue(model, null);
                var table = (DbSet)(typeof(LoginPageContentEntities).GetProperty(targetEntity).GetValue(db, null));
                table.AddRange((DbSet)modelValue);                         
                db.SaveChanges();
            }
}

I know that whatever TEntity is will match the modelValue data set. DbSet casting does not work and I am struggling to find how you can return an entire entity with generics. I have found that if I cast with (IEnumerable<TEntity>) I am able to call ToList() on table, however this will not work as I need to be able to call add range. Is it possible to:

  1. Return an entity reference with generics?
  2. Access AddRange and then save the context?

For context I am trying to replace this method:

public static void RevertChanges(Environments targetToRestoreFrom, ContentFields tableToRevert)
        {
            var jsonData = DataAccess.GetEnvironmentJson((int)targetToRestoreFrom);
            var model = JsonConvert.DeserializeObject<Models.FullDataSetModel>(jsonData);            
            using (var db = new LoginPageContentEntities())
            {
                switch (tableToRevert)
                {
                    case ContentFields.ProductInformation:
                        db.Database.ExecuteSqlCommand("TRUNCATE TABLE [ProductInformation]");
                        db.ProductInformation.AddRange(model.ProductInformation);
                        break;
                    case ContentFields.DidYouKnow:
                        db.Database.ExecuteSqlCommand("TRUNCATE TABLE [DidYouKnow]");
                        db.DidYouKnow.AddRange(model.DidYouKnow);
                        break;
                    case ContentFields.MaintenanceMessage:
                        db.Database.ExecuteSqlCommand("TRUNCATE TABLE [MaintenanceMessage]");
                        db.MaintenanceMessage.AddRange(model.MaintenanceMessage);
                        break;
                    case ContentFields.TrainingEvent:
                        db.Database.ExecuteSqlCommand("TRUNCATE TABLE [TrainingEvents]");
                        db.TrainingEvents.AddRange(model.TrainingEvents);
                        break;
                    case ContentFields.VideoContent:
                        db.Database.ExecuteSqlCommand("TRUNCATE TABLE [HtmlSnippets]");
                        db.HtmlSnippets.AddRange(model.HtmlSnippets);
                        break;
                    case ContentFields.ProductMarketingUrl:
                        db.Database.ExecuteSqlCommand("TRUNCATE TABLE [ProductMarketingUrl]");
                        db.ProductMarketingUrl.AddRange(model.ProductMarketingUrl);
                        break;
                }                
                db.SaveChanges();
            }
        }

Model:

namespace LoginPageContentManager.Models
{
    public class FullDataSetModel
    {
        public List<DidYouKnow> DidYouKnow                   { get; set; }
        public List<HtmlSnippets> HtmlSnippets               { get; set; }
        public List<MaintenanceMessage> MaintenanceMessage   { get; set; }
        public List<ProductInformation> ProductInformation   { get; set; }
        public List<TrainingEvents> TrainingEvents           { get; set; }
        public List<ProductMarketingUrl> ProductMarketingUrl { get; set; }
    }
}

Upvotes: 2

Views: 712

Answers (2)

Tim Rogers
Tim Rogers

Reputation: 21713

The Set<T> method allows you to get a DbSet generically.

In your case, you should be able to add to the set by doing:

db.Set<TEntity>().AddRange(modelValue)

Upvotes: 1

trailmax
trailmax

Reputation: 35106

You'll need to use Set(Type entityType) method on DbContext.

Something like this (not compiled or tested):

var setType = typeof(MyModel).GetProperty(targetEntity).GetType();
db.Set(setType).AddRange(modelValue)

Upvotes: 0

Related Questions