使用字符串而不是实体类

时间:2018-03-24 17:23:04

标签: c# entity-framework

我在Windows窗体应用程序(使用Entity Framework)中工作,我的数据库中有几个表。这些表是相似的(它们具有相同数量的具有相同列名的列),除了它们(表)具有不同的名称(这意味着,我有几个实体类)。

在firstForm(MainForm)上我有一个列表框,其中包含我拥有的所有表名。当用户选择其中一个时,新表单将打开(addForm)。在这个表单上,我有几个文本框来填充数据表。

我的问题是我想使用Entity Framework使用通用方法向表中添加数据。一般来说,如果我有一个名为Customer的表customerNamecustomerAge列(并且它对应的类具有相同名称),我会像这样添加数据:

using(var context = new MyDbContext())
{
     var newCustomer = new Customer {customerName = "Alex", customerAge = "24"};
     context.Customers.Add(newCustomer);
     context.SaveChanges();
}

我不想为我的数据库中的每个表编写代码。我认为,当在列表框中选择项目时,我必须将特定的类名称传递给构造函数,然后将此名称(字符串的类型)转换为特定的类,以将数据添加到与此名称关联的特定表中。

我怎么能这样做?

另一个例子 - Supplier表:

using(var context = new MyDbContext())
{
     var newSupplier = new Customer { supplierName = "Bob", supplierAge =  "20" };
     context.Suppliers.Add(newSupplier);
     context.SaveChanges();
}

3 个答案:

答案 0 :(得分:1)

如果所有项目的逻辑相同,您可以使用泛型并执行以下操作:

public class Writer<T> where T:class
{
    private DbContext _context;
    public Writer(DbContext context)
    {
        _context = context;
    }

    public void Insert(T obj)
    {
        _context.Set<T>().Add(obj);
        _context.SaveChanges();
    }
}

您必须为其提供EF上下文并指定您希望使用的类型。

希望这有助于至少指出正确的方向。

答案 1 :(得分:0)

您可以使用反射来完成此任务:

实体类和上下文类:

public class Person1
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Person2
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}

public class MyContext : DbContext
{
    public MyContext() : base ("connection string") { }

    public DbSet<Person1> Person1 { get; set; }
    public DbSet<Person2> Person2 { get; set; }
}

具有数据库名称的示例程序可以使用反射向其添加给定实体:

//I guess you can take this values from controls on your form
string database = "Person1";
int id = 1;
string name = "Charlie";
//get type of an entity
Type entityType = this.GetType().Assembly.GetTypes().Where(t => t.Name == database).First();
//geet object of an entity class
var entity = Activator.CreateInstance(entityType);
//set properties (name and id)
entity.GetType().GetProperty("Id").SetValue(entity, id);
entity.GetType().GetProperty("Name").SetValue(entity, name);
MyContext ctx = null;
try
{
    ctx = (MyContext)Activator.CreateInstance(typeof(MyContext));
    //here we'll loop thorugh properties of context (through databases),
    //if name match, add entity using reflection
    foreach (PropertyInfo property in ctx.GetType().GetProperties())
    {
        if (property.Name == database)
        {
            var dbSet = property.GetValue(ctx);
            //get Add method and invoke it with entity object
            dbSet.GetType().GetMethod("Add").Invoke(dbSet, new object[]{ entity });
            ctx.SaveChanges();
        }
    }
}
finally
{
    //always remeber to call Dispose method!
    if(ctx != null)
        ctx.Dispose();
}

答案 2 :(得分:0)

您可以使用DbContext.Database.ExecuteSqlCommand方法:

public class Customer : Entity
{
}

public class Supplier : Entity
{
}

public void CreateEntity(string TableName, Entity entity)
{
    using(var context = new MyDbContext())
    {
        var name = new SqlParameter("@name", entity.customerName);
        var age = new SqlParameter("@age", entity.customerAge); 

        context.Database.ExecuteSqlCommand($"insert into {TableName} (customerName, customerAge) values (@name, @age)", 
             name, age);
    }
}