C#数据库操作之LINQ to SQL技术详解
作者:木林森先生
一、LINQ to SQL技术概述
LINQ to SQL 是 .NET Framework version 3.5 的一个组件,提供了用于将关系数据作为对象管理的运行时基础结构。
在 LINQ to SQL 中,将关系数据库的数据模型,映射到一种对象模型中,该对象模型省指开发人员使用的编程语言表示的对象。通俗来讲,就是将数据库中的关系型数据,映射到代码里的实例对象。 当应用程序运行时,LINQ to SQL 会将对象模型中的语言集成查询转换为 SQL语句,然后将它们发送到数据库进行执行。 当数据库返回结果时,LINQ to SQL 会将它们转换回你可以用你自己的编程语言处理的对象。
【tips】使用Visual Studio的开发者可以使用对象关系设计器the Object Relational Designer,它为实现LINQ to SQL的许多特性提供了一个用户界面。
二、使用LINQ to SQL 进行简单操作.
通过使用 LINQ to SQL,使得访问 SQL 数据库,就像访问内存中的集合一样。
以下代码,创建一个Northwnd对象,代表northwnd数据库,并从Customers表中查询出城市为“London”的数据,返回一个集合,赋值给companyNameQuery,之后通过循环,输出集合内的元素。
// Northwnd inherits from System.Data.Linq.DataContext. Northwnd nw = new Northwnd(@"northwnd.mdf"); // or, if you are not using SQL Server Express // Northwnd nw = new Northwnd("Database=Northwind;Server=server_name;Integrated Security=SSPI"); var companyNameQuery = from cust in nw.Customers where cust.City == "London" select cust.CompanyName; foreach (var customer in companyNameQuery) { Console.WriteLine(customer); }
通过上述例子中,相必您已经体会到了LINQ to SQL技术的强大之处了,接下来,我将带领你们逐步的吸收LINQ to SQL技术。
三、如何动态创建数据库
在LINQ to SQL技术中,对象模型和关系型数据库之间是映射关系。要想启用映射关系,一般可以通过使用基于特性的映射,或者是使用描述关系数据库结构的外部映射文件。在这两种情况下,如果你有足够的关系型数据库的信息,那么就可以通过使用DataContext.CreateDatabase()方法来创建数据库实例。
DataContext.CreateDatabase()方法,仅在对象模型中被编码信息的范围内创建数据库的副本。对象模型中的映射文件和特性,不会对现有数据库结构的所有内容进行编码。映射信息不表示用户自定义函数、存储过程、触发器或检查约束的内容。这种行为对于各种数据库来说已经足够了。
如果已知的数据提供者是可用的(如SQL Server 2008),那么你可以在任何情况下使用DataContext.CreateDatabase()方法。
- →构建一个自动安装在客户系统上的应用程序。
- →构建一个客户机应用程序,该应用程序需要一个本地数据库来保存其脱机状态。
您还可以使用DataContext.CreateDatabase()方法来使用SQL Server,通过创建.mdf文件或目录名,具体是哪种取决于您的连接字符串。LINQ to SQL 使用连接字符串来定义将要创建的数据库,以及要创建数据连接的服务器。
【tips】尽可能的,请使用Windows集成安全性连接到数据库,以便在连接字符串中不需要密码。
案例一:
该例展示了一个如何创建一个名为MyDVDs.mdf数据库的方式。
//在使用该例展示的方法之前,必须进行以下两个步骤: //1、添加引用System.Data.Linq; //2、使用using语句,添加命名空间,否则报错 // using TableAttribute = System.Data.Linq.Mapping.TableAttribute; // using ColumnAttribute = System.Data.Linq.Mapping.ColumnAttribute; //Table特性,创建了数据库中的名为DVDTable的表与该类之间的映射关系。 [Table(Name = "MyOrders")] public class Order { //Column特性,创建了DVDTable表中同名列与该类成员属性之间的映射关系。 [Column(IsPrimaryKey = true)] public int id; [Column] public string name; [Column] public DateTime date; public override string ToString() { return "Order对象:{" + id + "," + name + "," + date + "}"; } } //自定义类 ,继承DataContext类。 public class MyOrders : DataContext { public MyOrders(String connection) : base(connection) { } public Table<Order> orders; } //创建一个MyOrders 类的对象db,该类继承自DataContext类。 MyOrders myOrders = new MyOrders(@"D:\myFirstOrder.mdf"); public void CreateDatabase() { if (myOrders.DatabaseExists()) { //先判断该路径中,是否存在该数据库文件,如果存在,则删除。 MessageBox.Show("Deleting old database..."); myOrders.DeleteDatabase(); } //myOrders对象创建数据库 myOrders.CreateDatabase(); //释放DataContext实例,所使用的的所有资源 //myOrders.Dispose(); }
【注意】
MyOrders myOrders = new MyOrders(@"D:\myFirstOrder4.mdf");
语句中的myOrders对象,最好设置成全局变量,如果设置成局部变量,后续在重复的调用方法时,可能会出现“该数据库已存在,请选择其他数据库名称”异常。
在构建自动安装在客户系统上的应用程序时,请先查看数据库是否已经存在,并在创建新数据库之前删除它。DataContext类提供DatabaseExists()和DeleteDatabase()方法来帮助您完成这个过程。
四、如何向数据库中insert数据
通过向关联的LINQ to SQL里的Table<TEntity>集合添加对象,然后向数据库提交更改,您就可以将行插入到数据库中。LINK to SQL将您提交的更改,翻译成适当的SQL insert语句,然后提交到数据库执行的。
【tips】您也可以为LINQ to SQL里默认的insert数据库、Update数据库、Delete数据库等操作进行重载。
以下步骤假设有一个连接到Northwind数据库的DataContext连接。
- 1、创建一个新对象,包含要提交的列数据。
- 2、将新对象添加到与数据库中目标表相关联的LINQ to SQL Table集合中。
- 3、提交更改到数据库中。
下面代码展示了创建一个新的Order对象(Order是用户自定义类),然后为它填充适当的属性值。之后将新的Order对象添加到Order集合里。最后,将更改提交到数据库,作为Orders表中一个新的行。
// Create a new Order object.Order class is user defined class. Order ord = new Order { id = 12000, name = "Harry Potty", OrderDate = DateTime.Now // … }; // Add the new object to the Orders collection. System.Data.Linq.Table<Order> table = myOrders.GetTable<Order>(); table.InsertOnSubmit(ord); // Submit the change to the database. try { myOrders.SubmitChanges(); } catch (Exception e) { MessageBox.Show(e.Message); // Make some adjustments. // ... // Try again. myOrders.SubmitChanges(); } //释放资源 //myOrders.Dispose();
【注意】在向数据库中的表里,insert数据或者后续的update、delete操作时,无论您对对象做了多少项更改,都只是在更改内存中的副本。 您并未对数据库中的实际数据做任何更改。 直到您对 显式调用DataContext里的SubmitChanges()方法 ,您所做的更改才会传输到服务器。
五、如何从数据库中query数据
LINQ to SQL 中的查询使用与 LINQ 中的查询相同的语法。 唯一的差异是 LINQ to SQL 查询中引用的对象映射到数据库中的元素。 有兴趣的朋友,可以看下 LINQ 查询知识。
下面的代码,展示了一个简单的查询请求,查询出id等于12000的订单,并将查询结果输出。
MyOrders myOrders = new MyOrders(@"c:\northwnd.mdf"); System.Data.Linq.Table<Order> table = myOrders.GetTable<Order>(); // Query for customers in London. IQueryable<Customer> custQuery = from order in myOrders.orders where order.id == 12000 select order; //将查询结果输出 foreach( var o in result) { Console.WriteLine(o.toString()); }
从数据库中查询数据,还有更多复杂的操作,后续我会继续整理更为详细的数据库查询操作,可以先关注下。
六、如何update表中的数据
通过修改与LINQ to SQL 的Table集合相关联的对象的成员值,然后将更改提交给数据库,那么就可以更新数据库中的某行数据。LINQ to SQL 将你的改变转换为相对应的SQL update语句。
将某行数据更新到数据库中的步骤如下:
1、在数据库中查询要更新的行。
2、对第1步的LINQ to SQL 查询结果里的成员值进行所需的更改。
3、将更改提交到数据库里。
下面的示例在数据库中查询订单#11000,然后更改结果order对象中的name和date的值。最后,对这些成员值的更改作为name和date列中的更改提交给数据库。
// Query the database for the row to be updated. var query = from ord in myOrders.Orders where ord.id== 11000 select ord; // Execute the query, and change the column values // you want to change. foreach (Order ord in query) { ord.name = "Hong Lou Meng"; ord.date = DateTime.Now; // Insert any additional changes to column values. } // Submit the changes to the database. try { myOrders.SubmitChanges(); } catch (Exception e) { MessageBox.Show(Console.WriteLine(e)); // Provide for exceptions. } //释放DataContext对象占用的资源。 //myOrders.Dispose();
七、如何如何delete表中的数据
可以通过从与表相关联的集合中删除相应的LINQ to SQL对象,来完成对数据库中某行的删除。LINQ to SQL 会将删除操作转变为适当的SQL delete语句。
LINQ to SQL不支持或不识别级联删除操作。如果你想删除表中有约束的一行,你必须完成以下其中一项条件:
1、在数据库的外键约束中设置ON DELETE CASCADE规则。
2、使用您自己的代码先删除阻止父对象被删除的子对象。
如果无法保证上述至少一个条件成立,则将抛出异常。请参阅本主题的第二个代码示例。
删除数据库中某一行的操作如下:
- 1、在数据库中查询需要删除的行。
- 2、调用DeleteOnSubmit方法。
- 3、将删除操作提交到数据库。
下面的第1个代码示例向数据库查询属于order# 11000的订单详细信息,将这些订单详细信息标记为删除,并将这些更改提交给数据库。
Table<Order> orders = myOrders.GetTable<Order>(); // Query the database for the rows to be deleted. var deleteResult = from ord in orders where ord.id == 11000 select ord; foreach (var ord in deleteResult ) { orders.DeleteOnSubmit(ord ); } try { myOrders.SubmitChanges(); } catch (Exception e) { MessagBox.Show(e.Message); // Provide for exceptions. }
在第二个代码示例中,目标是删除一个订单(#10250)。代码首先检查OrderDetails表,以查看要删除的订单在那里是否有子订单。如果订单有子订单,则首先将子订单标记为要删除,然后将订单标记为要删除。DataContext将实际的删除按正确的顺序排列,以便发送到数据库的删除命令遵守数据库约束。
//Northwnd myOrders = new Northwnd(@"c:\northwnd.mdf"); MyOrders myOrders = new MyOrders(@"D:\myFirstOrder.mdf"); myOrders.Log = Console.Out; // Specify order to be removed from database int reqOrder = 10250; // Fetch OrderDetails for requested order. var ordDetailQuery = from odq in myOrders.OrderDetails where odq.OrderID == reqOrder select odq; foreach (var selectedDetail in ordDetailQuery) { MessageBox.Show(selectedDetail.toString()); myOrders.OrderDetails.DeleteOnSubmit(selectedDetail); } // Display progress. MessageBox.Show("detail section finished."); // Determine from Detail collection whether parent exists. if (ordDetailQuery.Any()) { MessageBox.Show("The parent is present in the Orders collection."); // Fetch Order. try { var ordFetch = (from ofetch in myOrders.Orders where ofetch.OrderID == reqOrder select ofetch).First(); myOrders.Orders.DeleteOnSubmit(ordFetch); MessageBox.Show("{0} OrderID is marked for deletion.", ordFetch.OrderID); } catch (Exception e) { MessageBox.Show(e.Message); } } else { MessageBox.Show("There was no parent in the Orders collection."); } // Display progress. MessageBox.Show("Order section finished."); try { myOrders.SubmitChanges(); } catch (Exception e) { MessageBox.Show(e.Message); } // Display progress. MessageBox.Show("Submit finished.");
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。