연습: SQLite를 사용하여 로컬에 데이터 저장

완료됨

이 연습에서는 SQLite를 사용하여 애플리케이션에 로컬로 정보를 저장합니다. 샘플 시나리오에서는 응답성을 향상시키기 위해 소셜 미디어 앱에 대한 데이터를 캐시하기로 결정했습니다. 이 연습에서는 사용자에 대한 정보를 저장하기 위해 로컬 SQLite 데이터베이스를 만들고 사용합니다. 물리적 데이터베이스 파일을 로컬 스토리지에 저장합니다.

이 모듈에서는 .NET 8.0 SDK를 사용합니다. 기본 설정 터미널에서 다음 명령을 실행하여 .NET 8.0이 설치되어 있는지 확인합니다.

dotnet --list-sdks

다음 예제와 유사한 출력이 표시됩니다.

6.0.317 [C:\Program Files\dotnet\sdk]
7.0.401 [C:\Program Files\dotnet\sdk]
8.0.100 [C:\Program Files\dotnet\sdk]

8으로 시작하는 버전이 나열되어 있는지 확인합니다. 나열되는 버전이 없거나 명령을 찾을 수 없는 경우 최신 .NET 8.0 SDK를 설치합니다.

시작 솔루션 열기

  1. 연습 리포지토리를 복제하거나 다운로드합니다.

    참고 항목

    빌드 생성 파일이 최대 경로 길이를 초과하지 않도록 하려면 연습 콘텐츠를 C:\dev와 같은 짧은 폴더 경로에 복제하는 것이 가장 좋습니다.

  2. Visual Studio를 사용하여 mslearn-dotnetmaui-store-local-data>People에 있는 People.sln 솔루션 또는 Visual Studio Code의 시작 폴더를 엽니다.

    참고 항목

    아직 솔루션을 빌드하지 마세요. 코드는 불완전하며 이 연습의 뒷부분에서 누락된 요소를 추가할 때까지 컴파일되지 않습니다.

SQLite 엔터티 정의

  1. People 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가를 선택한 다음 새 폴더를 선택하여 프로젝트에 새 폴더를 추가합니다. 새 폴더의 이름을 Models로 지정합니다.

  2. Models 폴더를 마우스 오른쪽 단추로 클릭하고 추가를 선택한 다음 클래스를 선택합니다. 목록에서 클래스가 선택되었는지 확인한 다음 새 클래스 이름을 Person.cs로 지정합니다. 추가를 선택합니다.

  3. 클래스를 수정하고 public으로 표시합니다.

    namespace People.Models;
    
    public class Person
    {
    }
    
  4. Person 클래스에 Id라는 int 속성을 추가합니다.

  5. Name이라는 string 속성을 추가합니다. 이 클래스는 다음과 같이 표시되어야 합니다.

    namespace People.Models;
    
    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
  6. Person.cs 파일을 저장합니다.

SQLite 라이브러리 추가

  1. Visual Studio의 솔루션 탐색기에서 People 프로젝트를 마우스 오른쪽 단추로 클릭합니다.

  2. 표시되는 상황에 맞는 메뉴에서 NuGet 패키지 관리를 선택합니다.

  3. sqlite-net-pcl을 검색하여 선택한 다음 설치를 선택합니다.

    A screenshot showing the NuGet package manager with the sqlite-net-pcl library selected.

  4. 또한 SQLitePCLRaw.bundle_green을 검색하여 선택한 다음 설치를 선택합니다.

Visual Studio Code를 사용하는 경우 다음 명령을 사용하여 터미널과 이러한 패키지를 엽니다.

dotnet add package sqlite-net-pcl
dotnet add package SQLitePCLRaw.bundle_green

SQLite 특성 추가

  1. Person.cs 파일에서 SQLite 네임스페이스에 대한 using 지시문을 Person 클래스 파일에 추가합니다. 이 지시문을 사용하면 SQLite 특성을 사용할 수 있습니다.

    using SQLite;
    
    namespace People.Models;
    
    public class Person
    {
        ...
    }
    
  2. [Table] 특성으로 Person 클래스에 주석을 추가하고 테이블 이름을 people로 지정합니다.

  3. Id 속성을 기본 키로 지정합니다. [PrimaryKey][AutoIncrement] 특성으로 주석을 답니다.

  4. Name 속성에 주석을 추가합니다. MaxLength를 250으로 지정합니다. 열의 각 값이 Unique여야 함을 지정합니다.

    완료된 클래스는 다음과 같이 표시됩니다.

    using SQLite;
    
    namespace People.Models;
    
    [Table("people")]
    public class Person
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
    
        [MaxLength(250), Unique]
        public string Name { get; set; }
    }
    
  5. Person.cs 파일을 저장합니다.

데이터베이스에 연결

  1. PersonRepository.cs 파일을 엽니다.

  2. PersonRepository 클래스를 검사합니다. 이 클래스에는 데이터베이스 액세스 기능을 추가하는 TODO 마커가 있는 불완전한 기본 코드가 포함되어 있습니다.

  3. PersonRepository.cs 클래스의 파일에 SQLitePeople.Models 네임스페이스에 대한 using 지시문을 추가합니다.

  4. 클래스의 Init 함수 위에 conn이라는 프라이빗 SQLiteConnection 필드를 추가합니다.

  5. Init 함수에서 connnull과 같지 않은지 확인합니다. 그렇다면 즉시 반환합니다.

    if (conn != null)
        return;
    

    이렇게 하면 SQLite 데이터베이스의 초기화 코드가 한 번만 실행됩니다.

  6. _dbPath 변수를 사용하여 데이터베이스에 연결하려면 conn 필드를 초기화합니다.

  7. conn.CreateTable 메서드를 사용하여 Person 데이터를 저장할 테이블을 만듭니다. 완료된 Init 함수는 다음처럼 보입니다.

    using SQLite;
    using People.Models;
    ...
    
    private SQLiteConnection conn;
    ...
    private void Init()
    {
       if (conn != null)
          return;
    
       conn = new SQLiteConnection(_dbPath);
       conn.CreateTable<Person>();
    }
    

데이터베이스에 행 삽입

  1. PersonRepository 클래스에서 AddNewPerson 메서드를 찾습니다.

  2. 이 메서드의 TODO 주석을 새 Person 개체를 삽입하는 코드로 바꿉니다. 코드는 먼저 Init를 호출하여 데이터베이스가 초기화되었는지 확인한 다음 SQLiteConnection 개체의 Insert 메서드를 사용합니다. 다음 코드에 표시된 대로 result 변수를 Insert 메서드가 반환하는 값으로 설정합니다.

    public void AddNewPerson(string name)
    {
        int result = 0;
        try
        {
            // enter this line
            Init();
    
            // basic validation to ensure a name was entered
            if (string.IsNullOrEmpty(name))
                throw new Exception("Valid name required");
    
            // enter this line
            result = conn.Insert(new Person { Name = name });
            ...
        }
        ...
    }
    

데이터베이스에서 행 검색

  1. PersonRepository 클래스에서 GetAllPeople 메서드를 찾습니다.

  2. Init를 호출하여 데이터베이스가 초기화되었는지 확인합니다.

  3. 테이블의 모든 행을 검색하려면 일반 Table\<T> 메서드를 사용합니다. 형식 매개 변수로 Person을 지정합니다.

  4. 결과를 List\<Person> 컬렉션으로 변환하고 이 컬렉션을 반환하려면 ToList() 확장 메서드를 사용합니다.

  5. 코드를 try-catch 블록에 래핑하여 오류 처리를 추가합니다. 오류가 있는 경우 StatusMessage 속성을 예외의 Message 속성으로 설정하고 빈 컬렉션을 반환합니다. 완료된 메서드는 다음과 같습니다.

    public List<Person> GetAllPeople()
    {
       try
       {
          Init();
          return conn.Table<Person>().ToList();
       }
       catch (Exception ex)
       {
          StatusMessage = string.Format("Failed to retrieve data. {0}", ex.Message);
       }
    
       return new List<Person>();
    }
    
  6. PersonRepository.cs 파일을 저장합니다.

리포지토리를 UI에 통합

  1. MauiProgram.cs 파일을 엽니다.

  2. CreateMauiApp 함수에서 MainPage 페이지를 앱에 싱글톤 서비스로 추가하는 문 뒤에 다음 작업을 수행하는 코드를 추가합니다.

    • dbPath이라는 문자열 변수를 만듭니다. FileAccessHelper.GetLocalFilePath("people.db3") 식을 사용하여 이 문자열을 초기화합니다. 앱이 사용하는 데이터베이스 파일은 people.db3이며 앱은 이 파일을 디바이스의 로컬 스토리지에 저장합니다.

    • 종속성 주입을 사용하여 PersonRepository 클래스를 싱글톤 서비스로 앱에 추가합니다. PersonRepository 클래스는 데이터베이스 파일의 경로를 문자열 매개 변수로 사용하는 생성자를 노출합니다.

    CreateMauiApp 함수의 완료된 코드는 다음과 같습니다.

    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });
    
        // Add this code
        string dbPath = FileAccessHelper.GetLocalFilePath("people.db3");
        builder.Services.AddSingleton<PersonRepository>(s => ActivatorUtilities.CreateInstance<PersonRepository>(s, dbPath));
    
        return builder.Build();
    }
    
  3. MauiProgram.cs 파일을 저장합니다.

  4. 솔루션 탐색기에서 App.xaml을 확장한 다음 App.xaml.cs 파일을 엽니다.

  5. App 클래스에 PersonRepository 개체를 보유하려면 PersonRepo라는 public, static 속성을 추가합니다.

  6. PersonRepository 매개 변수를 생성자에 추가하고 'PersonRepo' 속성을 이 매개 변수의 값으로 설정하여 생성자에서 PersonRepo 속성을 초기화합니다. 완료된 App 클래스는 다음과 같이 표시됩니다.

    public partial class App : Application
    {
        public static PersonRepository PersonRepo { get; private set; }
    
        public App(PersonRepository repo)
        {
            InitializeComponent();
    
            MainPage = new AppShell();
    
            PersonRepo = repo;
        }
    }
    

참고 항목

종속성 삽입 프로세스는 생성자에 repo 매개 변수를 자동으로 채웁니다.

애플리케이션 테스트

  1. CTRL+Shift+B를 사용하여 솔루션을 빌드하고 F5를 사용하여 디버깅을 시작합니다. UI가 나타나면 이름을 입력하고 사용자 추가를 선택합니다.

    A screenshot of the app with a successful message stating a record has been added.

  2. 모든 사용자 가져오기를 선택하고 자신의 이름이 나타나는지 확인합니다.

    A screenshot of the app with a list of all the records in the database.

  3. 더 많은 이름을 추가하고 저장된 사용자 목록을 검색하여 실험합니다.

  4. Visual Studio 또는 Visual Studio Code로 돌아가서 Shift+F5를 사용하여 디버깅을 중지합니다.

  5. 앱을 다시 시작하고 모든 사용자 가져오기를 선택합니다. 이전에 저장한 이름이 데이터베이스에 여전히 저장되어 있는지 확인합니다. 완료되면 앱을 닫습니다.