ホームページ  >  記事  >  バックエンド開発  >  [ASP.NET MVC Mavericks Road] 06 - Entity Framework の使用

[ASP.NET MVC Mavericks Road] 06 - Entity Framework の使用

黄舟
黄舟オリジナル
2016-12-30 14:15:491436ブラウズ

[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 言語は非手続き型のセット指向のインタープリター型言語ですが、多くの高級言語は手続き型のオブジェクト指向のコンパイル型言語であるため、2 つの言語間に不一致が生じ、効率が不十分になります。この不整合を「インピーダンス不整合」と呼びますが、この「インピーダンス不整合」を解決するために登場したのがオブジェクトデータベースです。

リレーショナル データベース テクノロジでは、データを行と列の構造で保存および整理するためにテーブルが使用されることがわかっています。 .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 ソリューションで、主に Entity Data Model (EDM) に基づいています。 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,
)

然后随便在表中加几条用于测试的数据:

[ASP.NET MVC Mavericks Road] 06 - Entity Framework の使用

接下来我们就要让应用程序连接数据库了。由于上一篇博文是我在公司用休息的时间写的,公司的电脑装的是VS2010,家里的笔记本装的是VS2012,所以得重新把上篇博文的示例移到VS2012上,对于本示例,VS2010和VS2012都是一样的。上一篇示例项目的目录结构如下:

[ASP.NET MVC Mavericks Road] 06 - Entity Framework の使用

本文的示例将在上篇的这个示例基础上继续。

用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的。我们来看一下运行效果吧:

[ASP.NET MVC Mavericks Road] 06 - 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语句,结果如下:

[ASP.NET MVC Mavericks Road] 06 - Entity Framework の使用

结果证明使用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语句如下图:

[ASP.NET MVC Mavericks Road] 06 - Entity Framework の使用

我们看到改用IEnumerable后,EF生成的SQL没有任何过滤、排序等的操作,它一次把表中的所有数据都Select出来,和上面写的Linq表达式一点都没关系。

IQueryable虽然可以很智能地根据Linq表达式生成相应的SQL语句,但毕竟有一个分析Linq表达式的过程,相对来说性能比IEnumerable要差。那么我们什么时候用IEnumerable,什么时候用IQueryable呢?我想,对于少量的数据(比如从数据库中读取应用程序相关的系统信息)和不需要对数据进行过滤操作的情况,用IEnumerable比较适合;对于数据量较大需要对数据进行过滤(比如分页查询)的情况,则用IQueryable比较合适。

 以上就是[ASP.NET MVC 小牛之路]06 - 使用 Entity Framework的内容,更多相关内容请关注PHP中文网(www.php.cn)!


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。