.NET:Entity Framework 笔记

简介: 有二年没关注EF,今天无意试了下发现跟主流的Hibernate等ORM框架越来越接近了,先看下Entity类的定义: using System; using System.Collections.

有二年没关注EF,今天无意试了下发现跟主流的Hibernate等ORM框架越来越接近了,先看下Entity类的定义:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EFSample.Model
{

    [Table("T_ORDER")]
    public class Order
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { set; get; }

        [StringLength(50)]
        [Column("CUSTOMER_NAME")]
        public String CustomerName { set; get; }

        [Column("AMOUNT")]
        public decimal Amount { set; get; }

        public virtual ICollection<OrderItem> OrderItems { set; get; }

    
    }
}
View Code
 1 using System;
 2 using System.ComponentModel.DataAnnotations;
 3 using System.ComponentModel.DataAnnotations.Schema;
 4 
 5 namespace EFSample.Model
 6 {
 7     [Table("T_ORDER_ITEM")]
 8     public class OrderItem
 9     {
10         [Key]
11         [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
12         public int ID { set; get; }
13 
14         [ForeignKey("Order")]
15         [Column("ORDER_ID")]
16         public int OrderID { set; get; }
17 
18         [StringLength(50)]
19         [Column("PRODUCT_NAME")]
20         public String ProductName { set; get; }
21 
22         [Column("PRICE")]
23         public Decimal Price { set; get; }
24 
25         [Column("QUANTITY")]
26         public int Quantity { set; get; }
27 
28         public virtual Order Order { set; get; }
29 
30        
31     }
32 }
View Code

光看Attribute,已经跟Hibernate的Annotation很相似了。

配置文件:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <configuration>
 3   <configSections>    
 4     <section name="entityFramework"
 5        type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
 6   </configSections>
 7 
 8   <entityFramework>
 9     <contexts>
10       <context type="EFSample.DAL.OrderContext, EFSample" disableDatabaseInitialization="false">
11         <databaseInitializer type="EFSample.DAL.OrderInitializer, EFSample" />
12       </context>
13     </contexts>
14     <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
15       <parameters>
16         <parameter value="v11.0" />
17       </parameters>
18     </defaultConnectionFactory>
19     <providers>
20       <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
21     </providers>
22   </entityFramework>
23 
24   <startup>
25     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
26   </startup>
27 
28   <connectionStrings>
29     <!--连接字符串,使用SQLSERVER LocalDb-->
30     <add name="MyConn" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=OrderDatabase;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
31   </connectionStrings>
32   
33 </configuration>
View Code

注:LocalDb在开发阶段很方便,但是试用中有一个小问题,如果把生成的mdf物理文件删除后,再次运行总是报错(不知道是不是个别现象),只能把Initial Catalog=OrderDatabase中的文件名改成其它名称(比如:Catalog=OrderDb),才能正常运行。

此外,NuGet Package Manager工具搞得象java的maven一样,可以自动联机下载所需的依赖项,Tools->NuGet Package Manager

输入

Install -Package EntityFramework

就能自动向project添加相关的dll引用

DbContext

 1 using EFSample.Model;
 2 using System.Data.Entity;
 3 using System.Data.Entity.ModelConfiguration.Conventions;
 4 
 5 namespace EFSample.DAL
 6 {
 7     public class OrderContext:DbContext
 8     {
 9         public OrderContext() : base("MyConn") { }
10 
11         public DbSet<Order> Orders { set; get; }
12 
13         public DbSet<OrderItem> OrderItems { set; get; }
14 
15         protected override void OnModelCreating(DbModelBuilder modelBuilder)
16         {
17             modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
18         }
19     }
20 }
View Code

示例代码:

 1 using EFSample.DAL;
 2 using EFSample.Model;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 
 7 namespace EFSample
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             using (var db = new OrderContext())
14             {
15               
16                 //直接执行Sql语句
17                 db.Database.ExecuteSqlCommand("delete from t_order");
18 
19                 var orders = new List<Order>(){            
20                     new Order{ CustomerName="jimmy.yang",Amount=200, OrderItems=new List<OrderItem>(){
21                         new OrderItem(){ Price=10, Quantity=20, ProductName="Mobile"}
22                     }},
23                     new Order{ CustomerName="杨俊明",Amount=300, OrderItems=new List<OrderItem>(){
24                         new OrderItem(){ Price=15, Quantity=20, ProductName="架构之美"}
25                     }}};
26 
27                 //批量添加记录
28                 db.Orders.AddRange(orders);
29 
30                 //提交到db
31                 db.SaveChanges();                
32 
33                 //查询
34                 var query = db.Orders.Where(c => c.CustomerName == "Jimmy.yang").AsQueryable();
35 
36                 //输出Sql语句
37                 Console.WriteLine(query.ToString());
38 
39                 List<Order> orderEntities = query.ToList();
40 
41                 foreach (var order in orderEntities)
42                 {
43                     Console.WriteLine(String.Format("ID:{0}/CustomerName:{1}/Amount:{2}/ItemCount:{3}", order.ID, order.CustomerName, order.Amount,order.OrderItems.Count));
44                 }
45             }
46 
47             Console.WriteLine("ok!");
48             Console.Read();
49         }
50     }
51 }
View Code

输出:

SELECT
[Extent1].[ID] AS [ID],
[Extent1].[CUSTOMER_NAME] AS [CUSTOMER_NAME],
[Extent1].[AMOUNT] AS [AMOUNT]
FROM [dbo].[T_ORDER] AS [Extent1]
WHERE N'Jimmy.yang' = [Extent1].[CUSTOMER_NAME]


ID:9/CustomerName:jimmy.yang/Amount:200/ItemCount:1
ok!

对Oracle的支持

MS默认并没有提供EF对Oracle的支持,需要到Oracle官网下载 http://www.oracle.com/technetwork/topics/dotnet/downloads/index.html

下载比较慢,耐心等待,完成后,一路Next即可。

注意:tnsnames.ora文件的配置,一般在x:\app\client\Administrator\product\12.1.0\client_1\Network\Admin 目录下,参考内容如下:

1 XE =
2   (DESCRIPTION =
3     (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.187.128)(PORT = 1521))
4     (CONNECT_DATA =
5       (SERVER = DEDICATED)
6       (SERVICE_NAME = XE)
7     )
8   )

然后在vs中创建ADO.NET Entity Data Model时就能连接到Oracle db了,目前尚不支持Code-First,只能使用EF5,估计EF6要等明年才会正式发布
使用细节,可参考官网教程:http://www.oracle.com/webfolder/technetwork/tutorials/obe/db/dotnet/EntityFrameworkOBE/EntityFrameworkOBE.htm#t10

Sequence的处理:

Oracle中没有自增主键,msdn和oracle建议用trigger+sequence来处理自增主键的问题,即:insert前写个触发器,检测主键是否为空,如果为空,则将sequece.nextval赋值给它,参见:https://social.msdn.microsoft.com/Forums/th-TH/73453344-bbb9-4904-b77a-a9ba807dcfd2/oracle-e-entityframework?forum=mvcpt

示例代码:

1 create sequence S_CD_TIPO minvalue 1 maxvalue 9999999 start with 1 increment by 1;
2 
3 create or replace trigger tp_procedimento_trigger  
4 before insert on tp_procedimento for each row 
5 begin 
6   if :new.cd_tipo is null then select s_cd_tipo.nextval into :new.cd_tipo from dual; 
7   endif; 
8 end;

但我个人并不喜欢这种做法,感觉对db有点“侵入”,我比较喜欢在c#代码层掌控一切的感觉,如果大家跟我有一样的癖好,可以这么干:

 1 using System;
 2 using System.Data;
 3 using System.Data.Entity;
 4 
 5 namespace EntityFrameworkTest
 6 {
 7     public static class SequenceHelper
 8     {
 9         public static int GetNextVal(this DbContext db,String sequenceName) {
10             if (db.Database.Connection.State != ConnectionState.Open) {
11                 db.Database.Connection.Open();
12             }
13             var cmd = db.Database.Connection.CreateCommand();
14             cmd.CommandText = String.Format("select {0}.nextval from dual", sequenceName);
15             cmd.CommandType = CommandType.Text;
16 
17             int result = 0;
18             int.TryParse(cmd.ExecuteScalar().ToString(),out result);
19 
20             return result;
21         }
22     }
23 }

对DbContext写一个扩展方法,手动传入Sequence名称,然后在添加记录时,这样用:

 1 using System;
 2 using System.Linq;
 3 
 4 namespace EntityFrameworkTest
 5 {
 6     class Program
 7     {
 8         static void Main(string[] args)
 9         {
10             using (MyDbContext db = new MyDbContext())
11             {
12                 //insert
13                 T_BAS_AGENT newAgent = new T_BAS_AGENT();
14                 newAgent.AGENT = "XYZ";
15                 newAgent.CYEAR = 2014;
16                 newAgent.RECID = db.GetNextVal("SEQ_T_BAS_CARRIER");
17                 db.T_BAS_AGENT.Add(newAgent);
18                 db.SaveChanges();
19 
20                 //query
21                 var findAgent = db.T_BAS_AGENT.SingleOrDefault(c => c.RECID == newAgent.RECID);
22                 Console.WriteLine(string.Format("{0}/{1}/{2}", findAgent.RECID, findAgent.AGENT, findAgent.CYEAR));
23 
24             }
25 
26             Console.Read();
27         }
28     }
29 }

 

目录
相关文章
|
1月前
使用的是.NET Framework 4.0,并且需要使用SMTP协议发送电子邮件
使用的是.NET Framework 4.0,并且需要使用SMTP协议发送电子邮件
39 1
|
21天前
|
开发框架 缓存 监控
NET Framework 到 .NET 5/6 的迁移是重大的升级
本文详细介绍了从 .NET Framework 4.8 迁移到 .NET 5/6 的过程,通过具体案例分析了迁移策略与最佳实践,包括技术栈评估、代码迁移、依赖项更新及数据库访问层的调整,强调了分阶段迁移、保持代码可维护性及性能监控的重要性。
44 3
|
28天前
|
机器学习/深度学习 编解码 算法
【小样本图像分割-4】nnU-Net: Self-adapting Framework for U-Net-Based Medical Image Segmentation
《nnU-Net: 自适应框架用于基于U-Net的医学图像分割》是一篇2018年的论文,发表在Nature上。该研究提出了一种自适应的医学图像分割框架nnU-Net,能够自动调整模型的超参数以适应不同的数据集。通过2D和3D U-Net及级联U-Net的组合,nnU-Net在10个医学分割数据集上取得了卓越的性能,无需手动调整。该方法强调数据增强、预处理和训练策略等技巧,为医学图像分割提供了一个强大的解决方案。
59 0
【小样本图像分割-4】nnU-Net: Self-adapting Framework for U-Net-Based Medical Image Segmentation
winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
本文讨论了在基于.NET 6和.NET Framework的WinForms项目中添加图表控件的不同方法。由于.NET 6的WinForms项目默认不包含Chart控件,可以通过NuGet包管理器安装如ScottPlot等图表插件。而对于基于.NET Framework的WinForms项目,Chart控件是默认存在的,也可以通过NuGet安装额外的图表插件,例如LiveCharts。文中提供了通过NuGet添加图表控件的步骤和截图说明。
winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
|
3月前
|
开发框架 缓存 前端开发
实战.NET Framework 迁移到 .NET 5/6
从.NET Framework 迁移到.NET 5/6 是一次重要的技术革新,涵盖开发环境与应用架构的全面升级。本文通过具体案例详细解析迁移流程,包括评估现有应用、利用.NET Portability Analyzer 工具识别可移植代码、创建新项目、逐步迁移代码及处理依赖项更新等关键步骤。特别关注命名空间调整、JSON 序列化工具更换及数据库访问层重构等内容,旨在帮助开发者掌握最佳实践,确保迁移过程平稳高效,同时提升应用性能与可维护性。
112 2
|
3月前
|
数据库 C# 开发者
WPF开发者必读:揭秘ADO.NET与Entity Framework数据库交互秘籍,轻松实现企业级应用!
【8月更文挑战第31天】在现代软件开发中,WPF 与数据库的交互对于构建企业级应用至关重要。本文介绍了如何利用 ADO.NET 和 Entity Framework 在 WPF 应用中访问和操作数据库。ADO.NET 是 .NET Framework 中用于访问各类数据库(如 SQL Server、MySQL 等)的类库;Entity Framework 则是一种 ORM 框架,支持面向对象的数据操作。文章通过示例展示了如何在 WPF 应用中集成这两种技术,提高开发效率。
52 0
|
2月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
38 7
|
2月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
54 0
|
3月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
46 0