根据LINQ to SQL (Part 2 - Defining our Data Model Classes)翻译整理。载到了Visual C# “Orcas” Express Edition,因为该版本不支持SQL Server 2005 Developer Edition的链接,所以结合SQL Server Express Edition的AdventureWorks数据库,来分享一下LINQ设计器的使用。
一、创建用于SQL的LINQ数据模型
用于SQL的LINQ数据模型可以通过打开Visual Studio中的"Add New Item" 选项,并选中“LINQ to SQL”项来添加到ASP.NET,类库或Windows应用程序项目中。
当添加“LINQ to SQL”文件到项目中时,Visual Studio就会转到LINQ设计器界面,现在就可以进行建模操作了。同时,设计器会创建一个强类型的“DataContext”类,该类中的属性代表了从数据库中建模到LINQ中的每一个表,而方法则代表了我们选择建模的每一个存储过程,DataContext类是从数据库中查询实体集合和应用变化返回数据库的主要渠道。
如下图所示,这就是LINQ的ORM设计界面:
实体类:
用于SQL的LINQ可以建模映射数据库的类。这些类通常被称为“Entity Classes(实体类)”,它们的实例被称为“Entities(实体)”。实体类映射了数据库中的表,类中的属性通常映射了表中的字段,实体类的每一个实例则代表了数据库中表的一条记录。通过LINQ定义的实体类不继承于任何基类,这就意味着你可以让它继承于任意对象。而且使用LINQ设计器创建的类都被定义为“Partial Classes(局部类)”,所以就可以选择性的给类添加代码,附加属性、方法和事件。
与Visual Studio 2005提供的DataSet/TableAdapter功能不同的是,当使用LINQ设计器创建数据模型和访问层时不需要指定SQL查询语句。相应地,我们应该专注于实体类的定义,以及如何映射数据库和它们之间的关系。用于SQL的LINQ OR/M实现关心的是在运行时使用数据实体的时候,生成适当的SQL执行逻辑。使用LINQ查询语法通过强类型的方式来表达如何查询数据模型。
二、从数据库中创建实体类
如果有现有的数据库架构定义,可以通过它快速的创建LINQ中的实体类。当然,最简单的方式就是打开Visual Studio中的服务器浏览器(Express Edition中为Database Explorer——数据库浏览器),选中想要建模的表或视图,然后拖放到LINQ设计器界面中,就会自动生成对应的实体类:
三、命名与去复数化
需要注意的是,当使用LINQ设计器基于数据库架构创建实体类的时候,会自动“pluralizes(去复数形式)”。如果表名是“Employees”,类名就会是“Employee”,这种类命名方式会确保建模符合.NET命名约定。当然,也可以通过设计器或属性栏来对类和属性重命名:
实体/属性/关联拥有与数据库构架不同的命名的功能在一些情况下会十分有用,尤其是:
1.当后端数据库表/字段命名变化的时候。因为实体模型可以拥有不同的命名,所以仅仅更新映射规则就可以了,而不需要更新应用程序或用于新表/字段的查询代码。
2.当使用的数据库架构不是十分“整洁”的时候。例如,对于一个实体类中“au_lname”和“au_fname”的属性来说,可以重命名为“LastName”和“FirstName”来使用,而不必在数据库中重命名。
四、关系关联
当从服务器浏览器拖拽对象到LINQ设计器时,Visual Studio会自动检测对象间的主/外键关系,并根据它们创建不同实体间的默认“relationship associations(关系关联)”。例如,当把EmployeeAddress和Address都添加到LINQ设计器时,就会用箭头自动表示出一个一对多关联:
上面的关联会使EmployeeAddress实体类中拥有一个Address属性,这样就可以通过给定的EmployeeAddress来访问Address实体。同样的,Address实体类中会拥有一个“EmployeeAddress”集合来获取所有在该Address的EmployeeAddress记录。当然,也可以属性栏来修改设计器中选中关联的属性:
五、延迟/惰性读取
LINQ可以让开发者指定实体中的属性在第一次访问的时候是预读取还是延迟/惰性读取。通过选中实体的任一属性或关联,在属性栏中设置“Delay Loaded”属性为true或false。例如,现在有Document这样一个实体类,它所映射的数据库中的Document表中的Document字段存储了关于产品描述的文档资料,我们只想在实际使用它的时候再读取它。那么,就可以设置它的Deloy Loaded属性为true来延迟读取它:
注意:除了配置实体属性的预读取/延迟读取的默认值外,也可以在执行LINQ查询时,在代码中覆写它们的值。
六、使用存储过程
用于SQL的LINQ允许把存储过程以方法的形式建模到DataContext类中。例如,我们定义一个这样的存储过程——基于EmployeeID来查询Employee的Address信息:
我们可以在Visual Studio中通过把该存储过程拖拽到LINQ设计器,添加一个强类型方法来调用这个存储过程。如果拖动存储过程到LINQ设计器的“Address”实体上,如果该存储过程返回的表值结构与实体类中的属性匹配,设计器就会声明该存储过程会返回一个IEnumerable<Address>结果集:
七、使用存储过程更新/删除/插入数据
默认情况下,当更新/删除/插入实体时LINQ会自动生成适当的SQL表达式。当然也可以使用自定义的更新/删除/插入存储过程,在LINQ设计器中选中实体类,在属性栏中的Delete/Insert/Update上点击“...”,选择要使用的存储过程:
注意,改变以上的设置都只是纯粹的在LINQ映射层进行的处理,那么早先在程序中的代码就可以在不做任何改动的情况下继续工作。