2019. 12. 6. 15:30

드디어 EF(Entity Framework)를 연결합니다.

이 프로젝트는 코드 퍼스트(Code First)라 해당 코드가 들어 있지만

다른 방식을 사용한다면 코드 퍼스트 부분은 필요 없습니다.




1. EF(Entity Framework) 설치
이 내용은 자세하게 다룬 포스팅이 있으니 참고해 주세요.

참고 : [ASP.NET Core 2] EF(Entity Framework) 코어(Core) 코드 퍼스트(Code First)



이 프로젝트는 'SQLite'가 기준입니다.


누겟에서

Microsoft.EntityFrameworkCore.Tools

를 찾아 설치합니다.


사용하려는 DB에 맞는 프로바인더를 설치해야 합니다.

( 참고 : [ASP.NET Core 2] EF(Entity Framework) 코어(Core) 코드 퍼스트(Code First) )



2. DB 연결하기

DB 연결하기위해 커낵션 스트링(Connection String) 만들어 주고 연결하여 DB를 EF와 연동하여 객체화 해야 합니다.


2-1. 커낵션 스트링(Connection String) 만들기

'appsettings.json'파일을 열어 'ConnectionString'를 추가하여 커낵션 스트링을 추가해줍니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
  "Logging": {
    "LogLevel": {
      "Default""Warning"
    }
  },
 
  "SpaNetCoreFoundation_mssql": {
    "DBType""mssql",
    "ConnectionString""Server=[주소];DataBase=[데이터 베이스];UId=[아이디];pwd=[비밀번호]"
  },
 
  "SpaNetCoreFoundation_sqlite": {
    "DBType""sqlite",
    "ConnectionString""Data Source=ProjectFile\\SPAFoundation.db"
  },
 
  "AllowedHosts""*"
}
cs



'GlobalStatic'에 'DBString'을 추가합니다.


1
2
3
4
5
6
7
8
/// <summary>
/// DB 타입
/// </summary>
public static string DBType = "";
/// <summary>
/// DB 컨낵션 스트링 저장
/// </summary>
public static string DBString = "";
cs



'Startup.cs'를 열어  생성자에 위에서 만든 커낵션 스트링을 불러오는 코드를 넣습니다.


1
2
3
4
//DB 커낵션 스트링 받아오기
string sConnectStringSelect = "SpaNetCoreFoundation_sqlite";
GlobalStatic.DBType = Configuration[sConnectStringSelect + ":DBType"];
GlobalStatic.DBString = Configuration[sConnectStringSelect + ":ConnectionString"];
cs



이제 프로젝트가 시작되면 'appsettings.json'파일에서 'ConnectionString'을 받아올 수 있습니다.



2-2. DB 연결 준비하기
컨텍스트는 EF를 사용할 때 DB를 컨트롤하기 위한 객체입니다.

코드 퍼스트일 때는 모두 필요하지만 아닐 때는 필요 없는 부분이 있습니다.


2-2-1. DB모델용 폴더 만들기

먼저 'ModelDB'폴더를 만듭니다.


2-2-2. 'User' 클래스 만들기
'User' 클래스를 만들어 아래와 같이 작성합니다.

DB 퍼스트에서는 필요 없습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/// <summary>
/// 유저 사인인 정보.
/// 유저기준 정보임.
/// </summary>
public class User
{
    /// <summary>
    /// 고유키
    /// </summary>
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long idUser { get; set; }
 
    /// <summary>
    /// 사인인에 사용하는 이메일
    /// </summary>
    public string SignEmail { get; set; }
 
    /// <summary>
    /// 비밀번호
    /// </summary>
    public string Password { get; set; }
}
cs



2-2-3. 컨택스트 만들기

DB 퍼스트라면 이 부분은 자동으로 생성됩니다.


'SpaNetCoreFoundationContext'를 만들어 주고 아래와 같이 작성합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class SpaNetCoreFoundationContext : DbContext
{
    public SpaNetCoreFoundationContext(DbContextOptions options)
        : base(options)
    {
    }
 
    public DbSet<User> User { get; set; }
 
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().HasData(new User
        { 
            idUser = 1
            , SignEmail = "test01@email.net"
            , Password = "1111"
        }
        , new User
        { 
            idUser = 2
            ,
            SignEmail = "test02@email.net"
            , Password = "1111"
        });
    }
}
cs



2-2-4. 컨택스트 싱글톤 만들기

DB 컨텍스트를 관리하는 방법의 하나가 싱글톤을 만들어 사용하는 것입니다.

그런데 DB 컨텍스트는 싱글톤이 큰 의미가 없습니다.


사용하는데 결국 'using'문을 사용하여 그때그때 자원을 해제하지 않으면 엄청난 메모리 사용량을 자랑하게 됩니다.

'using'문을 사용하면 결국 쓸 때마다 새로 만들어 쓰게 되니 싱글톤이 의미가 없어집니다 ㅎㅎㅎ


이것이 옛날 예제에서는 자주 보이는데 이 프로젝트에서는 싱글톤 없이 그때그때 생성하여 사용하겠습니다.



2-2-5. 기존 유저 모델 제거

기존 모델인 'UserSignInfoModel'을 제거합니다.


나오는 오류를 위에서 만든 'User'모델로 연결하고 데이터는 'GlobalStatic.DBMgr'를 불러다 사용하면 됩니다.

(아직은 없는 게 맞습니다.)




3. DB 연결하기
이제 코드 퍼스트(Code First) 능력(?)을 사용해봅시다!

이것도 기본은 전에 쓴 포스팅과 같습니다.

참고 : [ASP.NET Core 2] EF(Entity Framework) 코어(Core) 코드 퍼스트(Code First)


3-1. DB 연결하기
'Startup.cs'의 'ConfigureServices'에 아래 코드를 추가합니다.

1
services.AddDbContext<SpaNetCoreFoundationContext>();
cs


3-2. 마이그레이션(Migration)을 만들고 업데이트하기

'마이그레이션(Migration) 정보를 생성하여 버전을 관리하고

이것을 DB에 업데이트하여 프로젝트의 모델 정보를 DB에 업데이트합니다.


아래 명령을 사용하여 마이그레이션을 생성합니다.


1
Add-Migration DB생성
cs



아래 명령을 사용하여 생성된 마이그레이션을 DB에 적용합니다.


1
update-database DB생성
cs



DB에 적용이 잘됐네요.




4. 기존 코드에 EF 사용

기존에 만들어둔 API에 새로 만든 EF를 이용하여 데이터를 검색하고 그 검색된 정보를 리턴하는 코드를 만들어 봅시다


4-1. 기존 코드 제거

기존에는 DB 대신 'GlobalStatic.UserList'를 사용하고 있었습니다.

이제 이 리스트는 필요 없으니 제거해 줍니다.


4-2. 기존 코드 수정
에러를 잡을 때 DB에 연결이 필요한 내용은 'using' 키워드를 이용해서 컨택스트를 생성해 줍니다.

'using' 키워드를 써야 함수가 끝날 때 컨택스트가 가비지 컬렉션을 통하지 않고 정리가 되어 바로 메모리에서 해제가 됩니다.


예>

1
2
3
4
5
6
using (SpaNetCoreFoundationContext db1 = new SpaNetCoreFoundationContext())
{
    User mgrItem
        = db1.User
            .FirstOrDefault(x => x.idUser == nID);
}
cs



5. 실시간 사인인 리스트 수정
실시간 사인인 리스트를 메모리에 저장하고 있는데 이것을 DB로 변경하겠습니다.


'ModelDB'폴더 밑에 'UserSignIn'를 생성하고 아래와 같이 작성합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/// <summary>
/// 유저 사인인 한 유저의 정보.
/// </summary>
public class UserSignIn
{
    /// <summary>
    /// 고유키
    /// </summary>
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long idUserSignIn { get; set; }
 
    /// <summary>
    /// 연결된 유저 사인인 정보
    /// </summary>
    [ForeignKey("idUser")]
    public User User { get; set; }
 
    /// <summary>
    /// 리플레시 토큰
    /// </summary>
    public string RefreshToken { get; set; }
}
cs



'SpaNetCoreFoundationContext'에 위에서 생성한 모델을 선언해 줍니다.


1
2
public DbSet<User> User { get; set; }
public DbSet<UserSignIn> UserSignIn { get; set; }
cs



마이그레이션을 생성하고 업데이트합니다.





'SignInItemModel'을 제거하고 오류 나는 부분은 'UserSignIn'으로 바꿔줍니다.


사인인 -> 사인아웃 해보면 DB가 수정되는 것을 확인 할 수 있습니다.




마무리

완성된 샘플 : Github dang-gun - SPA_NetCore_Foundation/SPA_NetCore_Foundation/SPA_NetCore_Foundation06/


DB까지 연결되었으니........

사실상 기능은 완성되었다고 볼 수 있습니다.


이대로 아래 폴더와 파일을 다른 프로젝트에 붙이고


wwwroot

Controllers

Global

IdentityServer4

Model

ModelDB

ProjectFile

User

appsettings.json

Startup.cs




누겟에서 라이브러리만 받아 설치하면 그대로 동작하게 됩니다.