1

I've got a method called AddFoo(Foo foo)

private int AddFoo(Foo foo)
{
  Using (BarContext db = new BarContext())
  {
    db.Foos.Add(foo);
    db.SaveChanges();
  }
  return foo.FooID;
}

I'd like to make it more generic to accept any entity and return an ID example (Rough and probably non functional just to show the idea:

private int Add(T entity)
{
  Using (BarContect db = new BarContext())
  {
    // need to figure out how to find the appropriate set
    DbSet dbSet = //Set Appropriate dbset based on entity type
    dbSet.Add(entity);
    db.SaveChanges(); 
  }
  return entity.PrimaryKeyValue; // this would be the integer value of the id
}

Now, I can use reflection to find an attribute marked with [Key] to figure out what property in the entity class holds the ID, but I don't think this is the most efficient. I can also hard code some map method that allows me to figure out what DBSet to add to... but I can't imagine that there isn't something out there that already does both these operations in a much more efficient way.

So... How can I determine the Key and it's value and How can I figure out what DbSet to use in something this generic?

UPDATE

Based on the answer below and the other similar post this is what I ended up doing... (pretty much just combined the two answers)

private static int GetEntityKeyValue<T>(this T entity) where T : class
{
  int ret = 0;
  PropertyInfo key = typeof(T).GetProperties().FirstOrDefault(p => p.GetCustomAttributes(typeof(KeyAttribute), true).Length != 0);
  if (key != null)
  {
    ret = (int)key.GetValue(entity, null);
  }
  return ret;
}

private static int Add<T>(T entity) where T : class
{
  using (Foo db = new FooContext())
  {
    DbSet dbset = db.Set<T>();
    dbset.Add(entity);
    db.SaveChanges();
  }
  return entity.GetEntityKeyValue();
}

I wanted to stay away from reflection... but, meh. Looks like that's the way.

Thanks all.

0

1 Answer 1

3

Your context has a Set<T>() method that will return the DBSet for the correct type.

This will make your method

private int Add(T entity)
{
  Using (BarContect db = new BarContext())
  {

    DbSet dbSet = db.Set<T>();
    dbSet.Add(entity);
    db.SaveChanges(); 
  }
  return entity.PrimaryKeyValue; // this would be the integer value of the id
}

Here is the MSDN for Set

http://msdn.microsoft.com/en-us/library/gg696521(v=vs.103).aspx

Sign up to request clarification or add additional context in comments.

6 Comments

I was just typing up this exact answer. +1
PrimaryKeyValue, does that exist? I always believed the only way to get it was .EntityKey.EntitiyKeyValues (since SQL entities can have multiple primary key properties...), unless you defined an interface on all your entities that says IHasPKValue and force you to have PrimaryKeyValue there ... , also, int is not a very generic solution here ...
Yeah, I missed that part of the question. I don't think the Add method should return anything. The Id will be set on the entity, the caller can access it that way.
the PrimaryKeyValue does not exist it was a placeholder for the example.
I generally have all my add calls return an int. Call it a throwback before the days of ORM, I'm just now learning EF. Before the pattern I followed was to use ADO.net directly and ALL of my adds returned the ID of the row inserted.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.