Entity Framework: create a model from the <TKey, TValue> dictionary to map to a database table

I used to have a table called ApplicationConfiguration that just had the [Key], [Value] columns to store some configuration data. This was immediately requested using SQL queries.

Now I intend to use the Entity Framework (EF) First method to query this table. A feature of this table is that the table will only have a fixed number of rows in its entire life. Only the Value column can be updated.

So, according to the first approach of the code, we must first write our POCO classes with their properties, which will be mapped to the columns in the base table. However, I want to have a Dictionary <> structure to represent these KV configuration pairs. My concern is whether EF can initiate update requests for any adjustment to the value of a particular pair.

In addition, since I use the Code First approach, I would like some source data (that is, a fixed number of rows and its initial content) to be added after the table itself was created on the fly when the application was first executed.

If the dictionary <> cannot be used, suggest an alternative. Thanks in advance.

+4
source share
2 answers

Coded as follows:

public class ApplicationConfiguration
{
    public int Id { get; set; }
    public string Key { get; set; }
    public int Value { get; set; } // should be string, but I'm lazy
}

class Context : DbContext
{
    internal class ContextInitializer : DropCreateDatabaseIfModelChanges<Context>
    {
        protected override void Seed(Context context)
        {
            var defaults = new List<ApplicationConfiguration>
            {
                new ApplicationConfiguration {Key = "Top", Value = 5},
                new ApplicationConfiguration {Key = "Bottom", Value = 7},
                new ApplicationConfiguration {Key = "Left", Value = 1},
                new ApplicationConfiguration {Key = "Right", Value = 3}
            };

//            foreach (var c in defaults)
//                context.ConfigurationMap.Add(c.Key, c); // by design, no IReadOnlyDictionary.Add

            foreach (var c in defaults)
                context.ApplicationConfigurations.Add(c);

            base.Seed(context);
        }
    }

    public Context()
    {
        Database.SetInitializer(new ContextInitializer());
    }

    private IDbSet<ApplicationConfiguration> ApplicationConfigurations
    {
        get { return Set<ApplicationConfiguration>(); }
    }

    public IReadOnlyDictionary<string, ApplicationConfiguration> ConfigurationMap
    {
        get { return ApplicationConfigurations.ToDictionary(kvp => kvp.Key, kvp => kvp); }
    }
}

Used as follows:

using (var context = new Context())
{
    ReadConfigurationOnly(context.ConfigurationMap);
}

using (var context = new Context())
{
    ModifyConfiguration(context.ConfigurationMap);
    context.SaveChanges();
}

static void ReadConfigurationOnly(IReadOnlyDictionary<string, ApplicationConfiguration> configuration)
{
    foreach (var k in configuration.Keys)
        Console.WriteLine("{0} = {1}", k, configuration[k].Value);
}

static void ModifyConfiguration(IReadOnlyDictionary<string, ApplicationConfiguration> configuration)
{
    foreach (var k in configuration.Keys)
        configuration[k].Value++; // this is why I was lazy, using an int for a string
}

So, I wrote it this way: - using the property int Value, and not string- just so that I can run the "Use this path" code again and again and each time to look at the database update, without creating an interesting way to change it Value.

It is not so indecent to use IReadOnlyDictionary<string, ApplicatonConfiguration>instead IReadOnlyDictionary<string, string>, as we would like, but this is more than compensated by the fact that we can easily change our collection values ​​without resorting to the clumsy method Set, taking the dictionary as input. The disadvantage, of course, is that we should be content configuration[key].Value = "new value", not configuration[key] = "new value", but - as I say - I think it's worth it.

EDIT

Dang! , , , , ... , Azure , app.config .

, ContextInitializer System.Configuration.ConfigurationManager ctor, app.config...

+2

, ; , , , . ... - (untested):

public Dictionary<string, string> GetDictionary()
{
Dictionary<string, string> dic = new Dictionary<string, string>();
using (var db = new Context())
{
    var configs = db.ApplicationConfiguration.Select();

    foreach (var entry in configs)
    {
       dic.Add(config.Key, config.Value);
    }
}
    return dic;
}

public void SaveConfig(Dictionary<string, string> dic)
{
    using (var db = new Context())
    {
        foreach (KeyValuePair kvp in dic)
        {
            if (!db.ApplicationConfiguration.First(a => a.Key == kvp.Key).Value == kvp.Value)
            {
                var ac = new ApplicationConfiguration();
                ac.Key = kvp.Key;
                ac.Value = kvp.Value;
                db.Entry(ac).State = EntityState.Modified;
            }
        }
        db.SaveChanges();
    }
}

Seed() . . .

+1

All Articles