使用不带实体框架的 C# 进行数据库交互
本文关键字:数据库 交互 框架 实体 | 更新日期: 2023-09-27 18:31:35
我被分配了一个任务,我需要显示一个表单,其数据驻留在 Sql 服务器的各个表中。要求是严格不使用实体框架或存储过程。在这种情况下,我有什么选择?
目前,我正在使用SqlCommand对象运行一些sql查询,但是在获取关系数据然后允许用户从表单中更新它时,事情变得非常复杂。
Winforms中允许查看和编辑关系数据的最佳方法/方法是什么?
您可以为需要访问/更新的对象编写自己的简单类。出于以下示例的目的,假设您有 2 个表:
人
- Person_Id int 主键不为空
- 名称 NVARCHAR(100) 空
电子邮件
- Person_Id int 主键不为空
- Email_Id int 主键不为空
-
电子邮件 NVARCHAR(100) 不空
public class MyProgram { public List<Person> ReadRecords() { // Set up your connection SqlConnection conn = new SqlConnection(); conn.Open(); SqlCommand cmd = new SqlCommand("SELECT * FROM Person", conn); SqlDataReader reader = cmd.ExecuteReader(); List<Person> personRecords = new List<Person>(); while (reader.Read()) { Person p = new Person(reader, conn); personRecords.Add(p); } return personRecords; } public int UpdateRecords(IEnumerable<Person> records, SqlConnection conn) { int personsUpdated = 0; int recordsUpdated = 0; foreach (Person p in records) { if (p.Changed) { recordsUpdated += p.Update(conn); personsUpdated++; } } return recordsUpdated; } } public class Person { public const string SqlGetPersonEmailsCommand = "SELECT Email_Id, Email FROM Emails WHERE Person_Id = @Person_Id"; public const string SqlUpdatePersonCommand = "UPDATE Person SET Name = @Name WHERE Id = @OriginalId"; public const string SqlUpdatePersonEmailCommand = "UPDATE Emails SET Email = @Email WHERE Email_Id = @Email_Id"; public int OriginalId { get; private set; } private bool personChanged; private bool emailsChanged { get { return changedEmails.Count > 0; } } public bool Changed { get { return personChanged || emailsChanged; } } private int _id; public int Id { get { return _id; } set { throw new Exception("Changing Id is not allowed."); } } private string _name; public string Name { get { return _name; } set { _name = value; personChanged = true; } } private List<int> changedEmails; private Dictionary<int, string> _emailAddresses; public string[] EmailAddresses { get { string[] values = new string[_emailAddresses.Count]; _emailAddresses.Values.CopyTo(values, 0); return values; } } public void UpdateEmail(int emailId, string newEmail) { _emailAddresses[emailId] = newEmail; changedEmails.Add(emailId); } public Person(IDataReader reader, SqlConnection conn) { // Read ID (primary key from column 0) OriginalId = _id = reader.GetInt32(0); // Check if value in column 1 is Null; if so, set _name to Null, otherwise read the value _name = reader.IsDBNull(1) ? null : reader.GetString(1); // Now get all emails for this Person record SqlCommand readEmailsCmd = new SqlCommand(SqlGetPersonEmailsCommand, conn); readEmailsCmd.Parameters.Add("@Person_Id", SqlDbType.Int); readEmailsCmd.Parameters["@Person_Id"].Value = OriginalId; SqlDataReader emailReader = readEmailsCmd.ExecuteReader(); changedEmails = new List<int>(); _emailAddresses = new Dictionary<int, string>(); if (emailReader.HasRows) { while (emailReader.Read()) { int emailId = emailReader.GetInt32(0); string email = emailReader.GetString(1); _emailAddresses.Add(emailId, email); } } } public int Update(SqlConnection conn) { int rowsUpdated = 0; SqlCommand command = null; // Update Person record if (personChanged) { command = new SqlCommand(SqlUpdatePersonCommand, conn); command.Parameters.Add("@OriginalId", SqlDbType.Int); command.Parameters["@OriginalId"].Value = OriginalId; command.Parameters.Add("@Name", SqlDbType.NVarChar); command.Parameters["@Name"].Value = _name; rowsUpdated = command.ExecuteNonQuery(); } // Now update all related Email records foreach (int id in changedEmails) { command = new SqlCommand(SqlUpdatePersonEmailCommand, conn); command.Parameters.Add("@Email_Id", SqlDbType.Int); command.Parameters["@Email_Id"].Value = id; command.Parameters.Add("@Email", SqlDbType.NVarChar); command.Parameters["@Email"].Value = _emailAddresses[id]; rowsUpdated = +command.ExecuteNonQuery(); } return rowsUpdated; } }
上面的示例支持更改人员的姓名和关联的电子邮件地址。
在这种情况下,我认为最好的方法是使用Dapper。您将非常接近 ADO.NET 并控制所有SQL查询。同时,您不会花时间在映射功能上 - 因为这非常简单,但耗时的代码部分。
-
问题#1以"[除了实体框架]我有什么选择?"结尾,你在评论中得到了答案(直截了当 ADO.NET 或NHibernate)。你也知道这一点,因为你说你正在使用 SqlCommand。
-
问题 #2 是困难的问题,我认为这就是您的导师希望您了解的:"Winforms 中允许查看和编辑关系数据的最佳方法/方法是什么?
我使用 Microsoft 堆栈为关系数据做了大量的 UI。但无论技术如何,您都需要一个好的模式或方法。简短的回答(不是一本书)是从 UI 中抽象数据。这样他们就可以独立工作,也可以独立改变。
首先意识到编辑数据和显示数据应该是程序的两个不同部分。我喜欢的一种方法是从SQL SERVER中选择您的关系数据作为XML,然后使用XSLT显示它:
<Customer>
<Name>...
<Company>...
<Phone>...
<BillingAddresses>
<Address>...
<Address>...
<PayementMethods>
<CreditCard>...
<CreditCard>...
<RecentOrders>
<Order>...
<Order>...
<Order>...
您可以使用 XSLT 轻松地将其转换为看起来像您想要的任何内容的 HTML。在此示例中,在显示每个<Address>
和<CreditCard>
的位置旁边,您可以在每个部分下放置"编辑/删除"链接以及"添加"链接。
单击"编辑/删除/添加"将转到一个屏幕,以修改该部分的关系数据。当您返回到将 XML 显示为 HTML 的屏幕时,您将看到更新的数据。
这很好,因为您可以轻松地修改 XML,而无需重新编译代码。还可以使用 XSLT 以所需的任何布局显示数据。然后,您的 XML 可以包含存储为代码的内容的文本(AMX=AMERICAN EXPRESS,等等)。
无论如何,这只是一个没有实际要求的解决方案(例如支持"撤消",一次应用多个更改等)。
数据库访问的最佳选择。这是 EF 所基于的技术。若要显示数据,大多数时间都使用数据绑定。用于保存和检索您使用的数据 ADO.NET。您可能不希望将 ADO 对象直接装箱到 UI,而是使用视图模型。但传统上和在文档中 ASP.NET 数据集通常直接绑定到UI女巫从今天看来是一种糟糕的编程风格。
创建数据集将是最佳选择。使用数据集的步骤1.右键单击您的项目,去添加=>新项目 =>数据集。那是.xsd格式文件。2.在该文件中右键单击数据集内,Agaign Add => 表适配器。从那里,您需要完成数据连接,然后选择表,开始编写查询。3. 完成创建后,可以直接将查询连接到类文件。