[ASP.NET
MVC The Road to Mavericks] 06 - Entity Framework 사용
집에서 한가롭게 지내도 괜찮습니다. 계속해서 [ASP.NET MVC The Road to Mavericks] 시리즈를 작성해 보겠습니다. . 이 시리즈의 이전 블로그 게시물에서는 도서 정보 목록을 표시할 때 프로그램 코드에서 데이터를 직접 작성했습니다. 이 문서에서는 ASP.NET MVC에서 Entity
Framework를 사용하여 데이터베이스에서 데이터를 가져오는 방법을 보여줍니다. 이 글의 제목은 비교적 간단해 보이지만, 주의 깊게 읽어보시면 분명 뭔가를 얻으실 수 있을 것이라 믿습니다.
이 기사의 디렉토리:
ORM 및 EF
애플리케이션을 개발하려면 데이터 표시 방법을 고려해야 합니다. 그리고 그것을 유지하는 방법. 이 문제를 고려할 때 우리가 가장 중요하게 고려해야 할 것은 프로그램의 성능, 개발의 용이성, 코드의 유지 관리 및 확장성입니다.
지속성이란 다양한 처리 상태 정보를 애플리케이션에 영구적으로 저장할 수 있는 메커니즘을 의미합니다. 지속성 메커니즘이 없으면 상태는 메모리에만 저장될 수 있으며 시스템이 종료되면 손실됩니다.
애플리케이션에서는 데이터를 영구적으로 저장하고 싶을 때 관계형 데이터베이스(Relation DataBase)를 선택하고, 일시적으로 데이터를 저장하고 싶을 때는 메모리에 저장된 객체를 사용합니다. 현재 대부분의 개발자는 관계형 데이터베이스 기술을 지속성 메커니즘으로 사용합니다. 현재 일부 사람들은 객체 데이터베이스(Object DataBase) 기술을 사용하려고 시도하고 있지만 관계형 데이터베이스 기술은 수년 동안 여전히 주요 지속성 메커니즘이 될 것입니다.
객체 데이터베이스는 왜 나타나는 걸까요? SQL 언어는 비절차적, 집합 지향적, 해석형 언어인 반면, 많은 고급 언어는 절차적, 객체 지향적, 컴파일형 언어입니다. 이로 인해 두 언어 간의 불일치가 발생하여 효율성이 만족스럽지 않습니다. 이러한 불일치를 "임피던스 불일치"라고 하며, "임피던스 불일치"를 해결하기 위해 객체 데이터베이스가 등장했습니다.
우리는 관계형 데이터베이스 기술에서 테이블이 행과 열 구조로 데이터를 저장하고 구성하는 데 사용된다는 것을 알고 있습니다. .NET 2.0 이전에는 C#에 제네릭이 없었을 때 사람들은 기본적으로 다음 코드와 같이 관계형 데이터베이스에서 쿼리된 데이터를 매핑하고 저장하기 위해 DataSet으로 채워진 DataTable을 사용했습니다.
using (SqlConnection conn = new SqlConnection(connString)) { using (SqlDataAdapter da = new SqlDataAdapter("Select * from order", conn)) { DataTable dt = new DataTable(); da.Fill(dt); ... } }
이 방법은 개체를 허용하지만 관계형 데이터베이스와 일치하는 지향 언어는 비형 안전성, 조작의 어려움, 낮은 성능과 같은 몇 가지 명백한 단점을 가지고 있습니다. .NET 2.0부터 사람들은 일반 기술을 통해 관계형 데이터베이스의 데이터를 일치시키기 위해 엔터티 모델 개체 컬렉션을 사용하기 시작했습니다. 이 방법은 DataTable 메서드의 단점을 해결했으며 강력한 타이핑, VS의 자동 완성, 컴파일 타임 기능을 제공합니다. 검사 및 기타 기능으로 인해 .Net 개발자들 사이에서 인기가 높습니다.
개발자가 이러한 "일치" 작업을 수동으로 수행하지 않아도 되도록 많은 ORM 도구(예: Entity Framework, NHibernate 등)가 개발되었습니다. ORM(Object Relation Mapping) 도구는 이름에서 알 수 있듯이 "관계"와 "객체 지향" 간의 "불일치"를 해결하는 것입니다. 이를 통해 개발자는 지속성 계층에 대해 너무 걱정하지 않고 더 많은 시간을 보낼 수 있습니다. 사업에.
Entity Framework(EF)는 ADO.NET을 기반으로 Microsoft에서 개발한 ORM 솔루션으로, 주로 EDM(Entity Data Model)을 기반으로 합니다. EF는 데이터 구조를 추상화하는 방법을 사용하여 애플리케이션에서 각 데이터베이스 객체를 클래스 객체(Entity)로 변환하고, 데이터 필드는 속성(Property)으로 변환되고, 관계는 연관 속성(Association)으로 변환되므로 데이터베이스의 E/R
모델은 객체 모델로 완전히 변환되어 개발자가 익숙한 객체지향 프로그래밍 언어를 사용하여 호출하고 액세스할 수 있습니다. EF 4.0 이상에서는 Database First, Model First 및 Code First의 3가지 세대 모드를 지원합니다. Code First 모드는 더 많은 사람들이 사용합니다.
개념이나 이론적인 내용은 많이 이야기하지 않겠습니다. 또한 질문이 있는 온라인 리소스를 검색하고 제가 이해한 내용을 바탕으로 요약했습니다. 하지만 언어를 정리하는 방법은 모릅니다.
이 글의 목적은 주로 독자들에게 EF에 대한 지각적인 이해를 제공한 다음, ASP.NET MVC에서 EF의 적용을 이해하는 것입니다. 다음에는 EF에 대해 별도로 소개하지 않겠습니다. .
Entity Framework 사용
이전 블로그 게시물 [ASP.NET
MVC Mavericks Road] 05에 이어 Ninject를 사용하여 이제 코드에서 직접 작성한 데이터를 다음과 같이 변경해야 합니다. 데이터베이스에서 읽습니다. 이를 위해 먼저 데이터베이스를 준비합니다. 이 예에서는 MS SQL Server를 사용하지만 다른 데이터베이스에도 동일하게 적용됩니다. 먼저 BookShop이라는 데이터베이스를 생성한 후 다음 스크립트를 실행하여 Books 테이블을 생성합니다.
CREATE TABLE Books ( [ID] INT NOT NULL PRIMARY KEY IDENTITY, [Title] NVARCHAR(100) NOT NULL, [Isbn] VARCHAR(20) NOT NULL, [Summary] NVARCHAR(1000) NOT NULL, [Author] NVARCHAR(50) NOT NULL, [Thumbnail] VARBINARY(MAX), [Price] DECIMAL(16, 2) NOT NULL, [Published] DATE NOT NULL, )
然后随便在表中加几条用于测试的数据:
接下来我们就要让应用程序连接数据库了。由于上一篇博文是我在公司用休息的时间写的,公司的电脑装的是VS2010,家里的笔记本装的是VS2012,所以得重新把上篇博文的示例移到VS2012上,对于本示例,VS2010和VS2012都是一样的。上一篇示例项目的目录结构如下:
本文的示例将在上篇的这个示例基础上继续。
用NuGet在BookShop.Domain工程中安装Entity Framework包,方法请参考本系列的上一篇文章。
在BookShop.Domain工程的Concrete文件夹中添加一个名为EFDbContext的类,代码如下:
public class EFDbContext : DbContext { public DbSet<Book> Books { get; set; } }
使用EF Code First第一步就是创建一个继承自System.Data.Entity.DbContext的类,这个类将为数据库中的每个表定义一个属性,属性的名称代表数据库中的表名。DbSet作为返回类型,它是用于生成CRUD(Create、Read、Update和Delete)操作的装置,映射数据库表的行。
我们需要在BookShop.WebUI工程中的web.config配置文件中添加数据库的连接字符串,来告诉EF怎样连接数据库。根据自己机器上的数据库配置连接字符串如下:
<connectionStrings> <add name="EFDbContext" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=BookShop;User ID=sa;Password=sa" providerName="System.Data.SqlClient" /> </connectionStrings>
接下来,我们把BookShop.Domain工程下Concrete文件中的BookRepository类文件改造一下,把代码中手工造的数据改成从数据库读取,以测试应用程序是否可以正常连接数据库。修改后的BookRepository类如下:
public class BookRepository : IBookRepository { private EFDbContext context = new EFDbContext(); public IQueryable<Book> Books { get { return context.Books; } } }
在我们的这个仓储类中,我们改使用EF,通过创建一个EFDbContext类的实例来获取数据库中的数据。如你所见,我们不需要自己写ADO.NET代码去连接和读取数据库,非常简洁明了,我们就是这样使用Entity Framework的。我们来看一下运行效果吧:
到这我们已经成功使用EF连接上了数据库,并从数据库中读取出来了数据。我们还可以通过Linq进行非常灵活的查询,就像写SQL一样。比如要查询价格在100元以下的前10条记录,并且按价格从低到高显示,那么我们可以在BookShop.WebUI工程下的BookController中的List方法中这样写:
public ViewResult List() { return View(repository.Books .OrderBy(b => b.Price) .Where(b => b.Price < 100) .Take(10)); }
或许你很快就会对EF获取数据库的方式产生这样的疑问:EF从数据库中读取整个Books表的数据到内存,然后返回给调用者(上面代码中的repository.Books)用Linq语句过滤用户想要的前10条数据,如果Books表中有几百万条数据,那内存岂不是完蛋了,EF不会这么傻吧?EF会不会根据Linq查询语句智能地生成SQL文本再到数据库中去查询数据呢?这里就要讲讲IQueryable和IEnumerable了。
IQueryable 和 IEnumerable
其实,对于上面的即有过虑又有排序的条件查询Linq语句,EF是读取数据库中整个Books表中的数据到内存,还是根据Linq查询语句智能的生成SQL再执行查询,完全编码者来决定的。我们打开BookShop.Domain工程的BookRepository类文件,请注意该类中Books属性的返回类型:
... public IQueryable<Book> Books { get { return context.Books; } }
我们对使用IQueryable作为返回类型提了个疑问:为什么用IQueryable而不用IEnumerable作为返回类型?答案是:使用IQueryable,EF会根据调用者的Linq表达式先生成相应的SQL查询语句,然后到数据库中执行查询,查询出来的数据即是用户想要的数据;而使用IEnumerable,Linq表达式的过滤、排序等操作都是在内存中发生的,即EF会先从数据库中把整个表的数据查询出来放在内存中,然后由调用者使用Linq语句进行过滤、排序等操作。是不是这样呢?我们来监视一下两种情况EF生成的SQL语句就知道了。
我们先来看看使用IQueryable的情况。重新运行一下程序,然后使用SQL Server Management Studio的活动和监视器查看一下我们的BookShop应用程序所执行的SQL语句,结果如下:
结果证明使用IQueryable,EF是先根据Linq表达式生成相应的SQL语句再执行查询的。
我们再稍稍修改一下代码来看看用IEnumerable的情况。把BookRepository类修改如下:
public class BookRepository : IBookRepository { private EFDbContext context = new EFDbContext(); public IEnumerable<Book> Books { get { return context.Books; } } }
当然BookRepository类所实现的IBookRepository接口(在BookShop.Domain工程的Abstract文件夹中)也要改一下:
public interface IBookRepository { IEnumerable<Book> Books { get; } }
再重新运行一下应用程序,用活动和监视器查看最后执行的SQL语句如下图:
我们看到改用IEnumerable后,EF生成的SQL没有任何过滤、排序等的操作,它一次把表中的所有数据都Select出来,和上面写的Linq表达式一点都没关系。
IQueryable虽然可以很智能地根据Linq表达式生成相应的SQL语句,但毕竟有一个分析Linq表达式的过程,相对来说性能比IEnumerable要差。那么我们什么时候用IEnumerable,什么时候用IQueryable呢?我想,对于少量的数据(比如从数据库中读取应用程序相关的系统信息)和不需要对数据进行过滤操作的情况,用IEnumerable比较适合;对于数据量较大需要对数据进行过滤(比如分页查询)的情况,则用IQueryable比较合适。
以上就是[ASP.NET MVC 小牛之路]06 - 使用 Entity Framework的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!