I'm working on a project with a C# MVC using Entity Framework 6.0 and I have a bunch of models like Customer, Promotion, Messages, and in all of them, I'm pretty space inefficient with repetitive error handling logic. For example, here's how I'm saving new customer records.
Note the length error checking!
public class CustomerRepository : IRepository<Customer>
{
private MyDBEntities db = new MyDBEntities();
public uniqueIdentifier AddRecord (Customer record) {
record.PromotionStatus = CheckForPromo(record);
record.LastOrderID = GetLastOrderID(record);
db.Customer.Add(record);
try {db.SaveChanges();}
catch (DbEntityValidationException e){
foreach (var err in e.EntityValidationErrors){
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following errors", err.Entry.Entity.GetType().Name, err.Entry.State);
foreach (var innerErr in err.ValidationErrors){
Console.WriteLine("--Property of \"{0}\" has error \"{1}\"" , innerErr.PropertyName, innerErr.ErrorMessage);
}
}
}
return record.id;
}//end of AddRecord
}
I have a couple different classes modeled in EF and in my tables, like so:
Each of them has a very similar looking save block like this:
db.Customer.Add(record);
try {db.SaveChanges();}
catch (DbEntityValidationException e){
foreach (var err in e.EntityValidationErrors){
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following errors", err.Entry.Entity.GetType().Name, err.Entry.State);
foreach (var innerErr in err.ValidationErrors){
Console.WriteLine("--Property of \"{0}\" has error \"{1}\"" , innerErr.PropertyName, innerErr.ErrorMessage);
}
}
}
The only thing different between them is whether it is db.Customer.Add(record);
, or db.Promotion.Add(record);
or so on.
I thought I could add a new method to my repo like this
private void TrySaveRecord(string recordType, object record){
db.recordType.Add(record);
try {db.SaveChanges();}
catch (DbEntityValidationException e){
foreach (var err in e.EntityValidationErrors){
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following errors", err.Entry.Entity.GetType().Name, err.Entry.State);
foreach (var innerErr in err.ValidationErrors){
Console.WriteLine("--Property of \"{0}\" has error \"{1}\"" , innerErr.PropertyName, innerErr.ErrorMessage);
}
}
}
}
But I ran into an issue of MyDbEntities does not contain a definition for 'recordType'
. Since then I've been spiraling around a whirlpool of depression, feels like this is probably doable but I don't know the vocabulary for this domain to figure out how to describe what I'm trying to do.
Thanks for any pointers :)
There are several ways you can handle it.
The most obvious is to let Add
outside from the helper method and handle only the SaveChanges
.
Another way is to make your helper method generic and use Set<T>()
method to access the associated DbSet
:
private void TrySaveRecord<T>(T record)
where T : class
{
db.Set<T>().Add(record);
// ...
Another way is to use GetType()
and the non generic Set(Type)
method:
private void TrySaveRecord(object record)
{
db.Set(record.GetType()).Add(record);
// ...
or similar, but using Entry(object)
method and setting the State
to EntityState.Added
(which in EF6 is the same as calling DbSet.Add
method):
private void TrySaveRecord(object record)
{
db.Entry(record).State = EntityState.Added;
// ...