Adding an Entity to the Entity Framework Dynamically Using Reflection

In the following code, the type domainObjectchanges (but ends with DO, which I crop next to get the corresponding table name). Having the name of the table and its type, I want to update an existing object — its name matches the name tableNamedue to EF — in the database with the new property values ​​from domainObject. Therefore, I must first find the POCO in the table with the same IDin order to overwrite this. This is the code so far:

public void Update(object domainObject)
{
  Type type = domainObject.GetType();
  string tableName = type.Name.Substring(0, type.Name.Length - 2);
  PropertyInfo tableProp = typeof(MyDbContext).GetProperty(tableName);
  Type tableType = tableProp.PropertyType;
  Type pocoType = tableType.GetGenericArguments()[0];

  int id = (int)type.GetProperty("ID").GetValue(domainObject);

  using (var context = new MyDbContext())
  {
    object table = tableProp.GetValue(context);
    MethodInfo singleMethod = tableType.GetMethod("Single");
  }
}

Usually, knowing the actual table, and not just its type, I now get POCO through

var poco = context.TableName.Single(item => item.ID == id);

There are 2 problems here:

(1) Single- extension method.

(2) I have no idea how to get a lambda expression in a form objectto pass it to Invokefrom Single.

- Reflection, ? (, table [ , , ], , , EF - "" , Add , ID , ). , , , !

+4
2

, , , , , :

object entity = context.Set(domainObject.GetType()).Find(id);

, :

ParameterExpression p = Expression.Parameter(domainObject.GetType());
Expression property = Expression.Property(p, "ID");
Expression c = Expression.Constant(id);
Expression body = Expression.Equal(property, c);
Expression exp = Expression.Lambda(body, new ParameterExpression []{ p });

MethodInfo singleMethod = typeof(Queryable).GetMethods()
    .Single(m => m.Name == "Single" && m.GetParameters().Count() == 2)
    .MakeGenericMethod(domainObject.GetType());

DbSet dbSet = context.Set(domainObject.GetType());
object entity = singleMethod.Invoke(null, new object[]{ dbSet, exp });

Expression , Single ( p => p.ID == id). Single Queryable. , . , linq Reflection.

+4

, DbSet.

public int Update<TEntity>(TEntity domainObject)
{
  int id = domainObject.Id; // Needs interface !!
  using (var context = new MyDbContext())
  {
    var objectInDb 
       = ctx.DbSet<TEntity>.Single(e => e.Id == id);  // Needs interface !!
    // Use ValueInjecter (not AutoMapper) to copy the properties
    objectInDb.InjectFrom(domainObject); // needs ValueInjecter Nuget Package
    context.SaveChanges();
  }
  return userId;
}

, , Id:

public interface IId
{
  public int Id { get; set; }
}

, :

public RepoClass<TEntity>
   where TEntity : IId
{
   // Define the generic method here
}

, Reflection.

- T4 - , POCO, , , :

public partial MyDomainClass : IId
{
}

wya Db.

, ValueInjecter, , Nuget Package Manager Install-Package ValueInjecter Nuget Package Manager.

using Omu.ValueInjecter; , InjectFrom , ( ). AutoMapper, .

, ( ) , ..

  var updatedObject = ctx.Set<TEntity>().Attach(domainObject);
  ctx.Entry(updatedObject).State = EntityState.Modified;
  ctx.SaveChanges();

, .

+3

Source: https://habr.com/ru/post/1543395/


All Articles