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

완료됨

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

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

dotnet --list-sdks

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

9.0.100 [C:\Program Files\dotnet\sdk]
10.0.100 [C:\Program Files\dotnet\sdk]

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

시작 솔루션 열기

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

    참고

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

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

    참고

    아직은 애플리케이션을 실행하지 마세요. 코드가 완전하지 않으며 나중에 이 연습에서 누락된 요소를 추가할 때까지 예외가 throw됩니다.

SQLite 엔터티 정의

  1. Models 폴더에서 Person.cs 파일을 엽니다.

  2. int 클래스에 Id라는 Person 속성을 추가합니다.

  3. string이라는 Name 속성을 추가합니다. 클래스가 다음과 같이 표시됩니다.

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

SQLite 라이브러리 추가

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

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

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

    sqlite-net-pcl 라이브러리가 선택된 NuGet 패키지 관리자를 보여 주는 스크린샷

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

dotnet add package sqlite-net-pcl

SQLite 특성 추가

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

    using SQLite;
    
    namespace People.Models;
    
    public class Person
    {
        ...
    }
    
  2. Person 특성으로 [Table] 클래스에 주석을 추가하고 테이블 이름을 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. using 클래스의 파일에 SQLitePeople.Models 네임스페이스에 대한 PersonRepository.cs 지시문을 추가합니다.

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

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

    if (conn != null)
        return;
    

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

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

  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. 새로운 Person 개체를 삽입하려면 이 메서드의 TODO 메모를 코드로 바꿉니다. 코드는 먼저 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. 결과를 ToList() 컬렉션으로 변환하고 이 컬렉션을 반환하려면 List\<Person> 확장 메서드를 사용합니다.

  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. public라는 static, PersonRepo 속성을 추가합니다. 이 속성은 PersonRepository 클래스에 대한 App 개체를 보유합니다.

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

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

참고

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

애플리케이션 테스트

  1. Ctrl+Shift+B를 사용하여 솔루션을 빌드합니다.

  2. 빌드가 완료되면 F5를 사용하여 디버깅을 시작합니다. UI가 나타나면 이름을 입력하고 [사람 추가]를 선택합니다.

    레코드가 추가되었다는 메시지가 표시된 앱의 스크린샷

  3. 모든 사용자 가져오기를 선택하고 이름이 표시되는지 확인합니다.

    데이터베이스의 모든 레코드 목록이 있는 앱의 스크린샷.

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

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

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