Kết nối cơ sở dữ liệu sử dụng Entity Framework trong winform – Series Giải pháp winforms (6)

0

Entity framework là một ORM (Object – Relational Mapper) được sử dụng phổ biến hàng đầu khi phát triển ứng dụng .NET. Entity Framework giúp làm việc với cơ sở dữ liệu trong winform một cách tiện lợi mà không cần quan tâm đến ngôn ngữ SQL. Khi làm việc với các cơ sở dữ liệu phức tạp, Entity Framework giúp giảm nhẹ công việc, hạn chế lỗi và đặc biệt tiện lợi.

Khi làm đề tài, đảm bảo rằng bạn sẽ phải sử dụng cơ sở dữ liệu. Khi đó, Entity Framework là công cụ không thể thiếu được.

Trong bài này, chúng ta sẽ xem xét cách sử dụng Entity Framework code-first để truy xuất dữ liệu với Sql Server trong winform.

Loạt bài “Các giải pháp dành cho lập trình winform”:
Phần 1 – Lỗi thường gặp trong lập trình winforms
Phần 2 – Thiết kế giao diện với Data Sources và BindingSource
Phần 3 – Phân chia code thành module sử dụng Interface
Phần 4 – Sử dụng thư viện DevExpress cho winforms
Phần 5 – Sử dụng Data Binding
Phần 6 – Sử dụng Entity Framework

ADO.NET và Entity Framework là gì

Trước khi Entity Framework ra đời, để kết nối ứng dụng winforms với sql server, người ta sử dụng nhóm class DataSet, DataTable, TableAdapter, DataAdapter của ADO.NET. Giao diện thiết kế của winforms giúp dễ dàng tạo ra các data source từ một cơ sở dữ liệu sử dụng các class trên. Từ data source dễ dàng tạo ra giao diện form như chúng ta đã làm. Toàn bộ code và truy vấn được sinh tự động.

Tuy nhiên, sau đó nhóm class DataSet không được khuyến khích sử dụng nữa. Các ứng dụng cần cơ sở dữ liệu quan hệ sau này đều sử dụng một ORM. Entity Framework là một trong số đó.

Để làm việc với Entity Framework trong winform có ba cách tiếp cận: code first, database first, model first. Với ứng dụng phát triển mới, code first là hướng phù hợp hơn cả. Database first là phương pháp phù hợp nếu đã có sẵn cơ sở dữ liệu. Model first sử dụng một giao diện thiết kế riêng của visual studio để tạo ra sơ đồ entity, sau đó tự động sinh code sql.

Trong bài viết này chúng ta sẽ sử dụng Entity Framework code-first.

Chúng tôi đã có một bài viết nhỏ để so sánh ADO.NET và Entity Framework. Bạn có thể đọc bài viết này trước nếu chưa phân biệt được hai anh này.

Cài đặt Entity Framework cho dự án winform

Trong phần này chúng ta sẽ cài đặt các thành phần cần thiết để sử dụng cơ sở dữ liệu cho ứng dụng.

Cài đặt SQL Server hoặc LocalDb

Entity Framework hoạt động chủ yếu với Sql Server. Các phiên bản đầy đủ của Sql Server phải trả phí.

Microsoft cung cấp phiên bản Express miễn phí. Phiên bản này đủ dùng với hầu hết các ứng dụng vừa và nhỏ (cơ sở dữ liệu < 10Gb).

Đối với người phát triển ứng dụng, Microsoft cung cấp phiên bản Developer – phiên bản đầy đủ, miễn phí nhưng chỉ được dùng cho phát triển ứng dụng. Không được sử dụng phiên bản này cho triển khai thực tế.

Link tải Sql Server từ trang của Microsoft. Tùy ý lựa chọn phiên bản Express hoặc Developer. Trong ví dụ này, chúng tôi sử dụng bản Express.

Khi cài đặt phiên bản Express có thể lựa chọn chỉ cài Core (nhẹ nhất), cài thêm các dịch vụ nâng cao (tìm kiếm full text và report), hoặc cài LocalDb.

LocalDb là một phiên bản gọn nhẹ của Sql Server chuyên dành cho giai đoạn phát triển ứng dụng.

Cài đặt Sql Server Express để sử dụng cùng Entity Framework
Lựa chọn cài đặt Sql Server Express

Để dễ dàng quản lý các cơ sở dữ liệu, bạn cũng nên cài đặt thêm Sql Server Management Studio. Bạn có thể đọc thêm về cách cài đặt SQL Server Express, SQL Server Management Studio.

Tạo cơ sở dữ liệu mới từ Visual Studio

Visual Studio cho phép tạo cơ sở dữ liệu mới hoặc kết nối tới các cơ sở dữ liệu có sẵn trong Sql Server. Ở đây chúng ta sẽ tạo ra một cơ sở dữ liệu mới đặt tên là Contacts trên server vừa cài đặt.

Mở Server Explorer (View => Server Explorer) và thực hiện theo các bước dưới đây:

Tạo cơ sở dữ liệu mới từ Visual Studio
Tạo cơ sở dữ liệu mới từ Visual Studio. Lưu ý Server name chỉ đặt một dấu chấm (localhost).

Khi hoàn thành chúng ta có một cơ sở dữ liệu mới Contacts như dưới đây

Cơ sở dữ liệu Contacts

Bạn có thể đọc thêm về cách kết nối tới Sql Server trong bài viết này.

Cài đặt Entity Framework từ NuGet

Trước hết cài đặt Entity Framework cho thư viện ViewModels.

Cài đặt Entity Framework cho ViewModels

Sau đó tiếp tục cài đặt Entity framework cho project App theo cách tương tự.

Lưu ý rằng, ViewModels là nơi chúng ta trực tiếp viết code sử dụng Entity framework. Entity Framework sẽ được sử dụng trong phương thức Load và Save để thực sự tải và lưu dữ liệu vào Sql Server. App là nơi cuối cùng sử dụng thư viện này.

Chúng ta phải cài đặt cho cả hai project. Nếu chỉ cài đặt ở thư viện nơi viết code truy xuất dữ liệu mà không cài đặt ở project chạy, ở giai đoạn runtime sẽ báo lỗi, mặc dù vẫn dịch thành công.

Cấu hình và sử dụng Entity Framework trong winform

Tạo lớp Context

Entity Framework yêu cầu phải xây dựng một class riêng kế thừa từ lớp DbContext. Lớp này chứa các collection để ánh xạ sang các bảng của cơ sở dữ liệu. Trong project ViewModels hãy tạo một class Context (file Context.cs) và viết code như sau:

using Models;
using System.Data.Entity;

namespace ViewModels
{
    class Context : DbContext
    {
        public Context() : base("ContactsConnectionString")
        {
        }

        public DbSet<Contact> Contacts { get; set; }
        public DbSet<Email> Emails { get; set; }
        public DbSet<Phone> Phones { get; set; }
    }
}

Ở đây lưu ý “ContactsConnectionString” là tên của một chuỗi kết nối (Connection String) mà chúng ta sẽ phải tạo ra sau này trong file cấu hình (App.config) của cả hai project ViewModels và App.

Sử dụng Context để tải và lưu dữ liệu

Mở mã nguồn của ContactsViewModel và điều chỉnh code của hai phương thức Load và Save như sau:

private readonly Context _context = new Context();

public void Load()
{
    //using (var stream = File.OpenRead("data.dat"))
    //{
    //    var formatter = new BinaryFormatter();
    //    var contacts = formatter.Deserialize(stream) as List<Contact>;
    //    ContactBindingSource.ResetBindings(false);
    //    ContactBindingSource.DataSource = contacts;
    //}
    _context.Contacts.Load();
    ContactBindingSource.ResetBindings(false);
    ContactBindingSource.DataSource = _context.Contacts.Local;

}
public void Save()
{
    _context.SaveChanges();
    //using (var stream = File.OpenWrite("data.dat"))
    //{
    //    var formatter = new BinaryFormatter();
    //    formatter.Serialize(stream, ContactBindingSource.DataSource);
    //}
}

Ở đây chúng ta sử dụng lớp Context vừa tạo để thực hiện tải và lưu dữ liệu từ Sql Server thay cho file dữ liệu.

Nếu muốn thực hiện lọc dữ liệu, bạn có thể áp dụng LINQ với phương thức Where đối với thuộc tính Local.

Thêm ConnectionString

Ngay sau khi cài đặt thư viện Entity Framework, trong project xuất hiện một file có tên gọi App.config dùng để chứa thông tin cấu hình. Chúng ta mở App.config của cả ViewModels và App và bổ sung thêm thông tin như dưới đây:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />  
  </configSections>
  <connectionStrings>
    <add name="ContactsConnectionString" connectionString="Data Source=.;Initial Catalog=Contacts;Integrated Security=True;Pooling=False" providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="mssqllocaldb" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="ContactsConnectionString" connectionString="Data Source=.;Initial Catalog=Contacts;Integrated Security=True;Pooling=False" providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="mssqllocaldb" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>

Lưu ý tên của chuỗi liên kết này phải là ContactsConnectionString như đã sử dụng khi tạo lớp Context.

Giá trị của thuộc tính connectionString lấy theo cách sau:

Lấy connectionstring từ data connection

Đọc thêm về cấu trúc và cách tạo connection string.

Sử dụng Entity Framework Migration

Đến giai đoạn này, nếu bạn build và chạy thử chương trình, Entity Framework sẽ tự động tạo các bảng dữ liệu mới. Chương trình của chúng ta đã có thể sử dụng Sql Server để lưu trữ dữ liệu.

Tất cả đều rất đơn giản đúng không ạ! Không có một tí tẹo truy vấn SQL nào!

Tuy nhiên, giờ nếu bạn thay đổi thiết kế của các model, ứng dụng vẫn sẽ build và chạy nhưng ngay khi truy xuất dữ liệu sẽ báo lỗi vì cấu trúc class và cơ sở dữ liệu không phù hợp. Chúng ta thực hiện thêm một cấu hình nữa để giúp đơn giản hóa công việc khi cần thay đổi model: sử dụng Migration.

Trước hết chuyển ViewModels thành startup project. Sau đó mở Package Manager Console (View => Other Windows => Package Manager Console), mục Default project chọn ViewModels, và nhập lệnh sau vào dấu nhắc lệnh PM> enable-migrations

Sau bước này trong project ViewModels sẽ tạo ra một folder Migrations với một class Configuration trong đó. Mở file code này ra và thay đổi dòng code này AutomaticMigrationsEnabled = false; thành AutomaticMigrationsEnabled = true;

Tiếp tục nhập lệnh PM> update-database. Chờ thực hiện xong, refresh Data Connections sẽ thu được kết quả như sau:

Các bảng dữ liệu được tạo ra bằng Update-Database

Chạy chương trình và thử thêm bớt dữ liệu

Chương trình chạy với Sql Server Express

Bonus: bắt và xử lý ngoại lệ trong winform

Mỗi khi chương trình winforms bị lỗi sẽ hiện ra hộp thoại thông báo đặc biệt. Hộp thoại này nhìn rất nặng nề với nhiều thông tin về nguồn gây lỗi. Với người sử dụng đầu cuối, những thông tin này không quá quan trọng (và không dễ hiểu). Nó cũng tạo ra cảm giác không ổn định của chương trình.

Các chương trình ứng dụng thường áp dụng bắt lỗi ở cấp cao nhất và đưa ra những thông báo nhẹ nhàng hơn cho người dùng. Ở phần bonus này chúng ta sử dụng một cách thức bắt lỗi thường gặp của windows forms.

Mở file Program.cs của project App và chỉnh lại code của lớp Program, phương thức Main, như sau:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Config.Register();

        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
        AppDomain.CurrentDomain.UnhandledException += (s, e) =>
            MessageBox.Show((e.ExceptionObject as Exception).Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        Application.ThreadException += (s, e) =>
            MessageBox.Show(e.Exception.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);


        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new DxContacts());
    }
}

Các lệnh trên giúp bắt tất cả các lỗi trên UI và hiển thị một hộp thoại báo lỗi nhẹ nhàng thay cho hộp thoại mặc định của windows forms. Cách thông báo lỗi này không tạo ra cảm giác crash nặng nề cho ứng dụng.

Kết luận

Đến đây chúng ta đã hoàn thành một chương trình đơn giản có áp dụng nhiều kỹ thuật quan trọng của .NET và windows forms.

Chúng ta dễ dàng để ý thấy việc xây dựng ứng dụng giờ đây đơn giản hơn rất nhiều. Chương trình tạo ra có hình thức tương đối chuyên nghiệp, hoạt động ổn định. Chúng ta có thể dễ dàng thay đổi các thành phần của UI mà không ảnh hưởng đến những thành phần còn lại.

Chúng tôi hi vọng loạt bài này bạn có thể giúp bạn phần nào trong việc thực hiện các project môn học, thực tập, đồ án.

Chúc bạn thành công!

Loạt bài “Các giải pháp dành cho lập trình winform”:
Phần 1 – Lỗi thường gặp trong lập trình winforms
Phần 2 – Thiết kế giao diện với Data Sources và BindingSource
Phần 3 – Phân chia code thành module sử dụng Interface
Phần 4 – Sử dụng thư viện DevExpress cho winforms
Phần 5 – Sử dụng Data Binding
Phần 6 – Sử dụng Entity Framework

Bình luận

avatar
  Đăng ký theo dõi  
Thông báo về