我是C#和Entity Framework的新手,我对数据库类的字段和初始化有疑问。
我在老师的程序中收到了一些代码,这些代码通过Entity Framework连接到MySQL数据库。
到目前为止,我们已经看到了一些示例,其中用于向数据库添加内容的内部方法首先创建它的实例。到目前为止我们所看到的一个例子:
using (var db = new p4_databaseEntities())
{
cp_car carEntity = new cp_car();
carEntity.make = car.make;
carEntity.model = car.model;
carEntity.year = car.year;
db.cp_car.Add(carEntity); //
db.SaveChanges();
MessageBox.Show("A Car has been added");
}
this.Close();
cp_car是数据库中的一个表和程序中的一个类。 db是数据库的当前实例。
现在,在我收到的代码中,这不是这样做的。它完成了另一件事。顺便说一下程序是一个Windows窗体。
在第一个窗体窗口中,在构造函数内部,他创建了一个新的数据库实例,并调用了一个名为init的方法 来自另一个名为LinqQueries的类。代码:
public Form1()
{
InitializeComponent();
p4_databaseEntities db = new p4_databaseEntities();
LinqQueries.Init(db);
this.CenterToScreen();
}
LinqQueries类如何显示:
private static p4_databaseEntities _db;
public static void Init(p4_databaseEntities db)
{
_db = db;
}
据我了解,他在构造函数中创建了一个新的数据库实例,在那里他还调用了init方法。然后,此方法将db对象定义为_db。现在,他使用_db而不是数据库从数据库中添加或删除数据的每一种方法。
我的问题是,这是否意味着init方法将类型为p4_databaseEntities(数据库类的名称)的静态字段指定为对象?那么_db的值是一个对象吗?它是对象的引用吗?而且我注意到他在对数据库进行更改时一遍又一遍地使用相同的字段,这使我相信它可能是一个不会在程序生命周期中消失的活动对象?
如果有人能澄清这一点,我将不胜感激。请原谅我所犯的任何错误或错误陈述,如果我以任何方式出错,请纠正我。我是C#和实体框架的新手。
事先谢谢
答案 0 :(得分:0)
您的描述中有点不准确。这归咎于你的困惑。
DbContext不是数据库,它表示与数据库的连接。如果构造DbContext对象,则可以通过DbSet中描述的实体访问数据库中的表。
虽然看起来DbSet表示数据库中的表,但它没有。例如,您通过DbSet访问的实体可以将ICollection作为成员,其中包含不属于表的项,但是包含在不同表中的项。访问此ICollection中的项会导致执行SQL Join,而无需键入连接
因此,DbConnection中的DbSet对象不表示数据库表,它表示对可以使用DbSet对象访问的属性的访问,包括数据库中与表有关系的所有对象的属性。 DbSet对象。
使用using语句的第一个代码是应该使用实体框架的正常方式。
为了隐藏数据库的设计,通常会引入一个单独的类,它是唯一应该使用DbContext的类。数据库的所有用户都应该使用单独的类进行通信。
这允许更改数据库的内部,而无需更改使用数据库的代码。
这可能是LinqQueries类的目的。用户应该调用LinqQueries的(可能是静态的)函数,而不是直接调用DbContext的函数。这样,数据库的内部结构可以更改,而无需更改LinqQueries函数的调用者。
事实上,LinqQueries只与一个DbContext进行通信。 LinqQueries不决定使用哪个DbContext。正确的功能很大程度上取决于LinqQueries的一个用户,他应该创建一个DbContext和Init LinqQueries。这个用户也应该知道何时不再需要LinqQueries,因为他必须Dispose()DbContext。
这种设计如果容易出错。假设设计师制作非常好的产品,他的产品将被许多用户使用(意味着软件,而不是运营商)。你怎么断言只有一个用户会调用Init函数?
如果您确实希望所有用户使用相同的Dbcontext,为什么不让LinqQueries的构造函数创建此DbContext。实际上设计类似于单例设计模式,所以为什么不将LinqQueries创建为单例。
LinqQuery的所有用户都应该使用相同的限制并且只有DbContext限制不必要地使用LinqQuery类的限制。
如果LinqQuery类的用户可以将DbContext传递给构造函数,则用户可以决定此特定LinqQueries对象应该使用哪个数据库。这在创建单元测试时非常方便:可测试代码可以与具有特定测试值的数据库一起使用,而不是使用原始数据库。
总而言之,设计师的目标还不清楚。恕我直言,这是一个糟糕的设计,你是对的,不清楚会发生什么。class LinqQueries
{
// default constructor: use the default DbContext
public LinqQueries()
{
this.DbContext = new p4_databaseEntities();
}
// special constructor: user provided dbContext
public LinqQueries(p4_databaseEntities dbContext)
{
this.dbContext = dbContext;
}
private readonly p4_databaseEntities dbContext;
public IEnumerable<...> GetMyElements(...)
{
return this.dbContext....;
}
}
这样,LinqQueries的每个创建者都会确切地知道要做什么,要么使用默认的p4_databaseEntities,要么创建自己的Dbcontext并在不再需要时处理它
using (var mydbContext = new p4_databaseEntities())
{
LinqQueries linqQueries = new LinqQueries(myDbContext);
// note that this constructor is very lightWeight!
var result = linqQueries.MyQeury(...);
}
这种方法非常安全。我所做的任何错误都不会影响LinqQuery类的任何其他用户的代码。