在 Entity Framework 中,如何在没有枚举所有可能 DbSet 的 switch 语句的情况下将通用实体添加到其对应的 DbSet?
In Entity Framework, how do I add a generic entity to its corresponding DbSet without a switch statement that enumerates all the possible DbSets?
我有两种类型的实体:员工实体和办公室实体,两者之间存在一对多关系,因此一个办公室有很多员工。对于 EF,在上下文文件中为每个实体创建一个 DbSet:
public DbSet<Office> Offices { get; set; }
public DbSet<Employee> Employees { get; set; }
我做的一个 EF 教程让我为特定实体执行 CRUD 方法。例如,下面的方法创建一个办公室并将其添加到办公室 DbSet(忽略 MVC 的东西——我不再这样做了):
public ActionResult Create([Bind(Include = "Address,BusinessName")] Office office)
{
try
{
if (ModelState.IsValid)
{
db.Offices.Add(office);
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DataException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
return View(office);
}
基本上我想强调的两件事是将 Office 对象传递到方法中,并通过显式写入 db.Offices:
将办公室添加到 Office DbSet
db.Offices.Add(office);
但是,我需要编写一个可以传入通用实体对象的方法,并将其添加到正确的 DbSet 中。我的方法的粗略想法是这样的(我忽略了所有 MVC 的东西):
public void Create(object entityToCreate)
{
db.CorrespondingEntityType.Add(entityToCreate);
db.SaveChanges();
}
假设我有一个 Employee 对象。我可以将这个 Employee 传递给 Create 方法,它可以看到这是一个 Employee,因此它会将它添加到 Employees DbSet。我不知道 EF 是否支持这个。另一种方法是创建一个 switch 语句,这种方式取决于传入的实体类型,我可以直接调用哪个 DbSet 来将实体添加到。但我想避免这种情况,因为我将与更多的实体合作,而不仅仅是这两个。此外,我将不得不为其他 CRUD 方法做类似的事情。
我看到了this documentation from msdn about the ObjectSet.AddObject Method,看起来应该有用,但我不确定它是如何工作的。
您可以考虑像这样的通用 class:
public class GenericRepository<T> where T : class
{
internal YourConext context;
internal DbSet<T> dbSet;
public GenericRepository(YourContext context)
{
this.context = context;
this.dbSet = context.Set<T>();
}
public virtual void Insert(T entity)
{
dbSet.Add(entity);
context.SaveChanges();
}
}
如果你有像...这样的扩展方法
public static void Create<T>(this DbContext db, T entityToCreate)
where T : class
{
db.Set<T>().Add(entityToCreate);
db.SaveChanges();
}
...C# 将为您进行类型推断。您可以将其称为...
db.Create(office);
...无需担心类型。当然你应该输入一个已知的实体类型。
我有两种类型的实体:员工实体和办公室实体,两者之间存在一对多关系,因此一个办公室有很多员工。对于 EF,在上下文文件中为每个实体创建一个 DbSet:
public DbSet<Office> Offices { get; set; }
public DbSet<Employee> Employees { get; set; }
我做的一个 EF 教程让我为特定实体执行 CRUD 方法。例如,下面的方法创建一个办公室并将其添加到办公室 DbSet(忽略 MVC 的东西——我不再这样做了):
public ActionResult Create([Bind(Include = "Address,BusinessName")] Office office)
{
try
{
if (ModelState.IsValid)
{
db.Offices.Add(office);
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DataException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
return View(office);
}
基本上我想强调的两件事是将 Office 对象传递到方法中,并通过显式写入 db.Offices:
将办公室添加到 Office DbSetdb.Offices.Add(office);
但是,我需要编写一个可以传入通用实体对象的方法,并将其添加到正确的 DbSet 中。我的方法的粗略想法是这样的(我忽略了所有 MVC 的东西):
public void Create(object entityToCreate)
{
db.CorrespondingEntityType.Add(entityToCreate);
db.SaveChanges();
}
假设我有一个 Employee 对象。我可以将这个 Employee 传递给 Create 方法,它可以看到这是一个 Employee,因此它会将它添加到 Employees DbSet。我不知道 EF 是否支持这个。另一种方法是创建一个 switch 语句,这种方式取决于传入的实体类型,我可以直接调用哪个 DbSet 来将实体添加到。但我想避免这种情况,因为我将与更多的实体合作,而不仅仅是这两个。此外,我将不得不为其他 CRUD 方法做类似的事情。
我看到了this documentation from msdn about the ObjectSet.AddObject Method,看起来应该有用,但我不确定它是如何工作的。
您可以考虑像这样的通用 class:
public class GenericRepository<T> where T : class
{
internal YourConext context;
internal DbSet<T> dbSet;
public GenericRepository(YourContext context)
{
this.context = context;
this.dbSet = context.Set<T>();
}
public virtual void Insert(T entity)
{
dbSet.Add(entity);
context.SaveChanges();
}
}
如果你有像...这样的扩展方法
public static void Create<T>(this DbContext db, T entityToCreate)
where T : class
{
db.Set<T>().Add(entityToCreate);
db.SaveChanges();
}
...C# 将为您进行类型推断。您可以将其称为...
db.Create(office);
...无需担心类型。当然你应该输入一个已知的实体类型。