보라코딩

Day 21, EF Core 본문

개발자가 되었다?

Day 21, EF Core

new 보라 2023. 9. 13. 18:35

Entity Framework Core

  • Microsoft에서 개발한 .NET Core 기반의 ORM 프레임워크
  • 데이터베이스와 객체 간의 매핑을 쉽게 처리할 수 있도록 도와줌
  • ORM 프레임워크의 표준적인 기능인 CRUD(Create, Read, Update, Delete)를 제공

 

장점

  • 객체 지향 프로그래밍 언어와 관계형 데이터베이스를 쉽게 매핑
  • 데이터베이스 마이그레이션을 쉽게 관리
  • 다양한 데이터베이스를 지원
  • LINQ를 사용하여 데이터를 조회

 

단점

  • 성능이 낮을 수 있음
  • 복잡한 데이터베이스 모델을 처리하는 데 어려움이 있을 수 있음
  • 마이그레이션이 복잡할 수 있음



ER Core 실습1

 

WPF 시작 - EF Core

Entity Framework Core에서 WPF 사용에 대한 시작 자습서

learn.microsoft.com

 

 

 

 

 

Product.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GetStartedWPF
{
    public class Product
    {
        // Product 관련
        public int ProductId { get; set; }
        public string Name {  get; set; }

        // Category 관련
        public int CategoryId { get; set; }
        public virtual Category Category { get; set; }       

    }
}




 

Category.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GetStartedWPF
{
    public class Category
    {   
        // Category 관련
        public int CategoryId { get; set; }
        public string Name { get; set; }

        // Product 관련
        public virtual ICollection<Product> Products
        { get; private set; } =
            new ObservableCollection<Product>();  // 데이터 바인딩에 유용
    }
}

 

ProductContext.cs

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GetStartedWPF
{
    // DataContext
    // 애플리케이션과 데이터베이스 간의 상호작용을 관리하고 엔터티(테이블)와의 매핑을 제공하는 핵심 구성 요소
    public class ProductContext : DbContext
    {
        // "Product" 엔터티와 데이터베이스 테이블 간의 매핑
        public DbSet<Product> Products { get; set; }

        // "Category" 엔터티와 데이터베이스 테이블 간의 매핑
        public DbSet<Category> Categories { get; set; }

        // 데이터베이스 컨텍스트의 구성을 설정하는 메서드를 재정의
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite(
                "Data Source=products.db");
            optionsBuilder.UseLazyLoadingProxies();
        }
    }
}

 

MainWindow.xaml

<Window x:Class="GetStartedWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:GetStartedWPF"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded">

    <Window.Resources>
        <CollectionViewSource x:Key="categoryViewSource"/>
        <CollectionViewSource x:Key="categoryProductsViewSource" 
                              Source="{Binding Products, Source={StaticResource categoryViewSource}}"/>
    </Window.Resources>

    <Grid>
        <DataGrid x:Name="categoryDataGrid" AutoGenerateColumns="False" 
              EnableRowVirtualization="True" 
              ItemsSource="{Binding Source={StaticResource categoryViewSource}}" 
              Margin="13,13,43,229" RowDetailsVisibilityMode="VisibleWhenSelected">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding CategoryId}"
                                Header="Category Id" Width="SizeToHeader"
                                IsReadOnly="True"/>
                <DataGridTextColumn Binding="{Binding Name}" Header="Name" 
                                Width="*"/>
            </DataGrid.Columns>
        </DataGrid>

        <DataGrid x:Name="productsDataGrid" AutoGenerateColumns="False" 
          EnableRowVirtualization="True" 
          ItemsSource="{Binding Source={StaticResource categoryProductsViewSource}}" 
          Margin="13,205,43,108" RowDetailsVisibilityMode="VisibleWhenSelected" 
          RenderTransformOrigin="0.488,0.251">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding CategoryId}" 
                            Header="Category Id" Width="SizeToHeader"
                            IsReadOnly="True"/>
                <DataGridTextColumn Binding="{Binding ProductId}" Header="Product Id" 
                            Width="SizeToHeader" IsReadOnly="True"/>
                <DataGridTextColumn Binding="{Binding Name}" Header="Name" Width="*"/>
            </DataGrid.Columns>
        </DataGrid>

        <Button Content="Save" HorizontalAlignment="Center" Margin="0,240,0,0" 
        Click="Button_Click" Height="20" Width="123"/>
    </Grid>


</Window>

 

MainWindow.xaml.cs

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace GetStartedWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private readonly ProductContext _context = new ProductContext();

        private CollectionViewSource categoryViewSource;

        public MainWindow()
        {
            InitializeComponent();

            //리소스에서 CollectionViewSource를 검색
            categoryViewSource = (CollectionViewSource)FindResource(nameof(categoryViewSource));
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // 데이터베이스가 생성되도록 합니다. (데모 목적으로만 사용됩니다).
            _context.Database.EnsureCreated();

            // 데이터베이스에서 카테고리를 Entity Framework Core로 로드합니다.
            _context.Categories.Load();

            // CollectionViewSource에 데이터를 바인딩합니다.
            categoryViewSource.Source =
                _context.Categories.Local.ToObservableCollection();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // 모든 변경 내용이 자동으로 추적되며, 삭제된 항목도 포함됩니다!
            _context.SaveChanges();

            // 그리드를 가장 최신 값으로 갱신합니다.
            categoryDataGrid.Items.Refresh();
            productsDataGrid.Items.Refresh();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            // 데이터베이스 연결을 정리합니다.
            _context.Dispose();
            base.OnClosing(e);
        }

    }
}




MySQL 연동 실습

User.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EFCore_MYSQL
{
    internal class User

    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Password { get; set; }
    }
}

 

DBContext.cs

using Microsoft.EntityFrameworkCore;
using System;


namespace EFCore_MYSQL
{
    internal class DBContext : DbContext
    {

        public DbSet<User> Users { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseMySql("Server=localhost;Database=wpf;User=root;Password=1234;", 
                    new MySqlServerVersion(new Version(8, 0, 34))); 
        }
    }
}

 

MainWindow.xaml

<Window x:Class="EFCore_MYSQL.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:EFCore_MYSQL"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <DataGrid Name="userGrid" AutoGenerateColumns="True"></DataGrid>
    </Grid>
</Window>

 

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace EFCore_MYSQL
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            Go();
        }


        private void Go()
        {
            using (var dbContext = new DBContext())
            {
                userGrid.ItemsSource = dbContext.Users.ToList();
            }
        }
    }
}

 

패키지 관리자 콘솔

dotnet ef migrations add abc321
dotnet ef database update abc321

 

 

 


 

CRUD

 

 

Exercise - Set up a migration - Training

Learn how to design the classes that represent the domain model, and then apply them to a database during a migration.

learn.microsoft.com

 

'개발자가 되었다?' 카테고리의 다른 글

Day 23, RabbitMQ  (0) 2023.09.15
Day 22, Akka  (0) 2023.09.14
Day 20, C#  (0) 2023.09.12
Day 19, C# _ Unit Test  (0) 2023.09.11
Day 18, C# (DB 연동_MySQL)  (0) 2023.09.08