0

This is a simple example on how I update a value in the database:

var context = new dbEntities();
var car = context.CarTable.Where(p => p.id == id).FirstOrDefault();
car.Make = "Volvo";
context.SaveChanges();

However, what I need to do now is to get the property by name instead. So this is what I in theory would like to do:

var context = new dbEntities();
var car = context.CarTable.Where(p => p.id == id).FirstOrDefault();
**car["Make"] = "Volvo";**
context.SaveChanges();

Is this possible in EF?

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
  • 8
    You can do this via reflection, but it's not recommended, since its very slow (http://stackoverflow.com/questions/1196991/get-property-value-from-string-using-reflection-in-c-sharp and http://stackoverflow.com/questions/619767/net-reflection-set-object-property) – DerApe Jul 12 '13 at 07:48
  • 5
    And why do you want to do that? – Satpal Jul 12 '13 at 07:48
  • Why do you need properties by name? – Bas Jul 12 '13 at 07:51
  • Whats wrong with the way you are doing it currently? – Gaz Winter Jul 12 '13 at 07:51
  • Create indexer in `car` class and use reflection but... – Leri Jul 12 '13 at 08:02
  • The reason you need this is if you want to have a mapping file where each user specifies which bit of data goes into which part of the object, and then you only want to write the code once. Looks like Javascript works better than C# in this case, very sad when the free language outshines the Microsoft one. – NH. Mar 27 '17 at 15:26

3 Answers3

2

I wouldn't use reflection since that would be slow.

You can use expression trees, especially if you cache the expressions. Check this link for an article about it. I would write a wrapper around the code in the article which takes an object and a propertyname (string), creates/caches the func using the code in the article (or retrieves it from the cache), and executes the func.

Maarten
  • 22,527
  • 3
  • 47
  • 68
  • I don't understand how this is different from reflection.. it is definitely still reflection.. just with cached `PropertyInfo` instances. – Simon Whitehead Jul 12 '13 at 08:28
  • The creation of the expression tree indeed involves reflection (you have to retrieve the propertyinfo). But, once you have the compiled expression tree you don't need reflection anymore, you just execute the compiled expression tree. So what gives you a better performances is a single usage of reflection to create a compile expression tree, versus, continuous usage of reflection to retrieve/set a property value using reflection. Once the expression tree is compiled, it is much faster, pretty much as fast a directly getting/setting the property value in code. – Maarten Jul 12 '13 at 09:00
  • You should cache the compiled expression trees (the resulting `Func` and `Action` values), not the `PropertyInfo` instances. – Maarten Jul 12 '13 at 09:01
0

The main question is really why do you need this?

The best way is still car.Make = "Volvo";.

If string-name is strongly needed, you can use Reflection:

var property = typeof (Car).GetProperty("Make");
property.SetValue(car, "BMW", null);

Here are 2 drawbacks:

  • Slow.
  • Compiler cannot check the string.

The other way - you can use indexer and switch:

 public class Car
    {
        public string Make { get; set; }

        public string this[String name]
        {
            set
            {
                switch (name)
                {
                    case "Make":
                        Make = value;
                        break;
                    ...
                }
            }
        }
    }

And then just car["Make"] = "Volvo"; It's faster, but a typ-problem occurs: you have to parse strings or operate with objects.

0
public class Car
{
    public string Make { get; set; }

    public object this[string name]
    {
        get
        {
            var property = this.GetType().GetProperties().FirstOrDefault(p => p.Name.Equals(name));

            if (property != null)
            {
                return property.GetValue(this, null);
            }

            return null;
        }
        set
        {
            var property = this.GetType().GetProperties().FirstOrDefault(p => p.Name.Equals(name));

            if (property != null)
            {
                property.SetValue(this, value, null);
            }
        }
    }
}
Avram Tudor
  • 1,468
  • 12
  • 18