내보내기(0) 인쇄
모두 확장

Windows Phone의 로컬 데이터베이스 개요

2012-02-09

Windows Phone OS 7.1 을 사용하면 응용프로그램의 격리된 저장소 컨테이너에 있는 로컬 데이터베이스에 관계형 데이터를 저장할 수 있습니다. Windows Phone 응용프로그램은 모든 데이터베이스 작업에 LINQ to SQL을 사용합니다. LINQ to SQL은 데이터베이스 스키마를 정의하고, 데이터를 선택하고, 격리된 저장소에 있는 기본 데이터베이스 파일에 변경 사항을 저장하는 데 사용됩니다. 이 항목에서는 Windows Phone 응용프로그램에서 로컬 데이터베이스를 사용하는 방법을 간단하게 설명합니다. 로컬 데이터베이스를 사용하는 응용프로그램을 만드는 단계별 연습을 보려면 방법: Windows Phone용 기본 로컬 데이터베이스 응용프로그램 만들기를 참조하십시오.

로컬 데이터베이스에 데이터를 저장하고 검색하기 위해 Windows Phone 응용프로그램은 LINQ to SQL을 사용합니다. LINQ to SQL은 데이터 작업에 대한 개체 지향적 방법을 제공하고 개체 모델과 런타임으로 구성됩니다.

LINQ to SQL 개체 모델은 주로 로컬 데이터베이스의 프록시 역할을 하는 System.Data.Linq.DataContext 개체로 구성됩니다. LINQ to SQL 런타임은 개체부분(DataContext 개체)과 데이터 부분(로컬 데이터베이스)을 연결합니다. 다음 이미지는 이 관계를 요약하여 보여 줍니다.

Windows Phone DataContext 및 로컬 데이터베이스

데이터 컨텍스트는 데이터베이스를 나타내는 개체인 프록시입니다. 데이터 컨텍스트에는 각각 데이터베이스의 테이블을 나타내는 Table 개체가 포함되어 있습니다. 각 Table 개체는 데이터베이스의 데이터 행에 해당하는 엔터티로 구성됩니다. 각 엔터티는 특성을 가진 "POCO(Plain Old CLR Object)"입니다. 각 엔터티의 특성이 데이터베이스 테이블 구조를 결정하고 데이터 개체 모델과 데이터베이스 스키마 간의 매핑을 정의합니다. 예를 들어 NamePhoneNumber 속성이 있는 엔터티는 NamePhoneNumber 열이 있는 데이터베이스 테이블을 생성합니다.

LINQ to SQL은 관리되는 응용프로그램이 LINQ(Language Integrated Query)를 사용하여 Transact-SQL만 "전달"하는 관계형 데이터베이스와 통신할 수 있게 하는 개체 관계형 매핑 기능을 제공합니다. LINQ to SQL은 .NET Framework 관리 코드로 표현하는 개체 모델을 관계형 데이터베이스에 매핑합니다. 응용프로그램을 실행하면 LINQ to SQL이 LINQ(Language Integrated Query)를 Transact-SQL로 변환한 다음 실행을 위해 쿼리를 데이터베이스로 보냅니다. 데이터베이스에서 결과가 반환되면 LINQ to SQL이 결과를 개체로 다시 변환하며, 사용자가 고유한 프로그래밍 언어에서 이 개체로 작업할 수 있습니다. 자세한 내용은 LINQ to SQL을 참조하십시오.

참고참고:

Windows Phone 의 LINQ to SQL은 DDL(Data Definition Language) 또는 DML(Data Modeling Language) 문을 비롯한 Transact-SQL 실행을 직접 지원하지 않습니다. 또한 Windows Phone 응용프로그램은 LINQ to SQL을 사용하여 ADO.NET 개체에 직접 액세스할 수 없습니다. 자세한 내용은 Windows Phone에 대한 LINQ to SQL 지원을 참조하십시오.

SQL Server 관계형 데이터베이스를 사용하는 데스크톱 응용프로그램과 마찬가지로 Windows Phone 응용프로그램은 로컬 데이터베이스를 사용하여 LINQ to SQL을 통해 데이터를 선택, 삽입, 업데이트 및 삭제할 수 있습니다. 그러면 Windows Phone 응용프로그램이 LINQ의 강력한 쿼리 기능과 관계형 데이터베이스의 효율적인 저장 공간을 모두 활용할 수 있습니다. 휴대폰은 PC보다 리소스가 적기 때문에 로컬 데이터베이스와 표준 데이터베이스 간에 몇 가지 차이점이 있습니다. 차이점은 다음과 같습니다.

  • 로컬 데이터베이스가 Windows Phone 응용프로그램의 프로세스에서 실행됩니다. Microsoft SQL Server 등의 클라이언트-서버 데이터베이스와 달리 백그라운드 서비스로 계속 실행되지 않습니다.

  • 해당 Windows Phone 응용프로그램만 로컬 데이터베이스에 액세스할 수 있습니다. 데이터베이스 파일이 격리된 저장소에 있기 때문에 다른 응용프로그램은 이 데이터에 액세스할 수 없습니다.

  • LINQ to SQL을 통해서만 로컬 데이터베이스에 액세스할 수 있습니다. Transact-SQL은 지원되지 않습니다.

표준 응용프로그램 배포에서는 처음 응용프로그램을 실행할 때 격리된 저장소에 로컬 데이터베이스가 생성됩니다. 그 후에는 응용프로그램을 사용할 때 응용프로그램 데이터가 데이터베이스에 추가됩니다. 미리 채워진 참조 데이터 집합을 응용프로그램과 함께 포함하려면 로컬 데이터베이스 파일을 응용프로그램에 추가합니다. 단계별 지침은 방법: Windows Phone 응용프로그램과 함께 참조 데이터베이스 배포를 참조하십시오.

응용프로그램과 함께 참조 데이터를 배포하려면 다음 단계를 수행해야 합니다.

  1. 도우미 응용프로그램 만들기: 도우미 응용프로그램은 개발 컴퓨터에서 실행되며, 격리된 저장소에 로컬 데이터베이스를 만들고, 데이터베이스에 원하는 참조 데이터를 로드합니다.

  2. 도우미 응용프로그램에서 로컬 데이터베이스 추출: 격리된 저장소 탐색기(ISETool.exe)를 사용하여 도우미 응용프로그램에서 컴퓨터의 폴더로 데이터베이스를 복사합니다. 격리된 저장소 탐색기에 대한 자세한 내용은 방법: 격리된 저장소 탐색기 도구 사용을 참조하십시오.

  3. 주 응용프로그램 만들기: 참조 데이터를 사용할 응용프로그램을 만듭니다.

  4. 주 응용프로그램에 참조 데이터 추가: Visual Studio를 사용하여 컴퓨터에 저장한 폴더에서 주 응용프로그램으로 로컬 데이터베이스 파일을 추가합니다. 응용프로그램 어셈블리의 크기를 최소화하려면 파일을 콘텐츠로 저장합니다.

응용프로그램과 함께 배포한 로컬 데이터베이스는 읽기 전용 상태로 설치 폴더에 있습니다. 설치 폴더는 격리된 저장소와 다릅니다. 이 위치에 있는 데이터베이스 파일을 처리하려면 appdata: 접두사를 사용합니다. 데이터베이스 연결 문자열과 함께 이 접두사를 사용하는 방법의 예는 Windows Phone의 로컬 데이터베이스 연결 문자열을 참조하십시오.

참조 데이터가 포함된 데이터베이스를 수정하려면 데이터베이스 변경을 시도하기 전에 설치 폴더에서 이동하여 격리된 저장소에 저장합니다. 데이터베이스 파일을 이동하려면 Application.GetResourceStream 메서드로 스트림 기반 복사를 수행하여 설치 폴더에서 스트림을 만들고 IsolatedStorageFileStream.Write 메서드를 사용하여 격리된 저장소에 스트림을 쓸 수 있습니다. 다음 예제에서는 스트림 개체를 만들 때 설치 폴더의 데이터베이스 파일을 처리하는 방법을 보여 줍니다.

Stream str = Application.GetResourceStream(new Uri("appdata:/MyReferenceDB.sdf", UriKind.Relative)).Stream;

로컬 데이터베이스를 만들려면 먼저 데이터 컨텍스트와 엔터티를 정의해야 합니다. 이러한 클래스는 데이터 개체 모델과 데이터베이스 스키마 간의 매핑을 정의합니다. LINQ to SQL의 개체 관계형 기능은 이 매핑 정보를 사용하여 해당 데이터 컨텍스트에 매핑되는 관계형 데이터베이스를 만듭니다.

각 엔터티에 대한 매핑 정보는 LINQ to SQL 매핑 특성을 사용하여 지정됩니다. 이러한 특성은 테이블, 열, 기본 키, 인덱스 등의 데이터베이스 관련 기능을 지정합니다. 자세한 내용은 특성 기반 매핑(LINQ to SQL)을 참조하십시오. 예를 들어 다음 코드는 ToDoDataContext라는 데이터 컨텍스트와 ToDoItem이라는 엔터티 클래스의 시작 부분을 보여 줍니다.

public class ToDoDataContext : DataContext
{
    // Specify the connection string as a static, used in main page and app.xaml.
    public static string DBConnectionString = "Data Source=isostore:/ToDo.sdf";

    // Pass the connection string to the base class.
    public ToDoDataContext(string connectionString): base(connectionString) { }

    // Specify a single table for the to-do items.
    public Table<ToDoItem> ToDoItems;
}

// Define the to-do items database table.
[Table]
public class ToDoItem : INotifyPropertyChanged, INotifyPropertyChanging
{
    // Define ID: private field, public property, and database column.
    private int _toDoItemId;

    [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
    public int ToDoItemId
    {
        get
        {
            return _toDoItemId;
        }
        set
        {
            if (_toDoItemId != value)
            {
                NotifyPropertyChanging("ToDoItemId");
                _toDoItemId = value;
                NotifyPropertyChanged("ToDoItemId");
            }
        }
    }
         . . .
         . . .
         . . .

참고참고:

이 코드는 데이터 컨텍스트 코드의 일부일 뿐입니다. 로컬 데이터베이스를 사용하는 응용프로그램을 만드는 단계별 연습을 보려면 방법: Windows Phone용 기본 로컬 데이터베이스 응용프로그램 만들기를 참조하십시오.

코드에서 로컬 데이터베이스 기능을 사용하려면 코드 파일의 맨 위에 다음 지시문이 필요합니다.


using System.Data.Linq;
using System.Data.Linq.Mapping;
using Microsoft.Phone.Data.Linq;
using Microsoft.Phone.Data.Linq.Mapping;

다음 표에서는 일반적인 LINQ to SQL 매핑 특성 중 일부를 보여 줍니다. 전체 목록을 보려면 System.Data.Linq.Mapping 네임스페이스를 참조하십시오.

특성

예제

설명

TableAttribute

[Table]

클래스를 데이터베이스 테이블과 연결된 엔터티 클래스로 지정합니다.

ColumnAttribute

[Column(IsPrimaryKey = true)]

클래스를 데이터베이스 테이블의 열과 연결합니다. IsPrimaryKey는 기본적으로 인덱스가 생성되는 기본 키를 지정합니다.

IndexAttribute

[Index(Columns="Column1,Column2 DESC", IsUnique=true, Name="MultiColumnIndex")]

테이블 수준에서 작성하면 테이블에 추가 인덱스를 지정합니다. 각 인덱스가 하나 이상의 열을 처리할 수 있습니다.

AssociationAttribute

[Association(Storage="ThisEntityRefName", ThisKey="ThisEntityID", OtherKey="TargetEntityID")]

외래 키와 기본 키 간의 연결 등의 연결을 나타내는 속성을 지정합니다.

DataContext 개체를 만든 후 로컬 데이터베이스를 만들고 많은 데이터베이스 작업을 추가로 수행할 수 있습니다. 다음 코드 예제에서는 ToDoDataContext 클래스 데이터 컨텍스트를 기준으로 데이터베이스를 만드는 과정을 보여 줍니다.

// Create the database if it does not yet exist.
using (ToDoDataContext db = new ToDoDataContext("isostore:/ToDo.sdf"))
{
    if (db.DatabaseExists() == false)
    {
        // Create the database.
        db.CreateDatabase();
    }
}

이 예제에 표시된 것처럼 데이터 컨텍스트를 만들려면 데이터 컨텍스트와 데이터베이스 파일의 파일 위치를 먼저 지정해야 합니다. DataContext 생성자 값은 데이터베이스 파일 이름을 ToDo.sdf로 지정합니다. 이 값의 isostore:/ 부분은 파일이 격리된 저장소에 있도록 지정합니다. DatabaseExists 메서드에서 데이터베이스가 아직 없는 것을 확인한 후 CreateDatabase 메서드를 사용하여 데이터베이스를 만듭니다.

참고참고:

데이터베이스가 생성되면 자동으로 버전 0이 할당됩니다. 데이터베이스 버전을 확인하려면 이 항목의 뒷부분에 있는 데이터베이스 스키마 변경에 표시된 대로 DatabaseSchemaUpdater 클래스를 사용합니다.

로컬 데이터베이스가 생성된 후 LINQ 및 데이터 컨텍스트를 사용하여 로컬 데이터베이스 작업을 할 수 있습니다. 다음 하위 단원에서는 데이터베이스의 데이터를 선택, 삽입, 업데이트 및 삭제하는 방법에 대해 설명합니다. 이러한 작업을 수행하는 응용프로그램을 만드는 단계별 연습을 보려면 방법: Windows Phone용 기본 로컬 데이터베이스 응용프로그램 만들기를 참조하십시오.

데이터 선택(데이터베이스 쿼리)

Windows Phone 에서 LINQ(Language Integrated Query)를 사용하여 데이터베이스를 쿼리합니다. LINQ는 개체 부분과 데이터 부분 사이의 간격을 메웁니다. LINQ to SQL의 쿼리는 LINQ의 쿼리와 동일한 구문을 사용합니다. LINQ 쿼리에 대한 자세한 내용은 LINQ 쿼리 소개(C#)를 참조하십시오.

LINQ to SQL 쿼리에서 참조된 개체가 데이터베이스의 레코드에 매핑되어 있으므로 LINQ to SQL은 쿼리 실행 방법이 다른 LINQ 기술과 다릅니다. 일반적인 LINQ 쿼리는 메모리의 응용프로그램 계층에서 실행됩니다. LINQ to SQL에서 런타임의 개체 관계형 기능을 사용하면 각 LINQ 쿼리가 Transact-SQL로 변환된 다음 데이터베이스에서 직접 실행됩니다. 이 경우 큰 데이터베이스에서 몇 개의 레코드 선택과 같은 쿼리를 실행할 때 성능이 향상될 수 있습니다.

다음 예제에서는 toDoDB라는 DataContext 개체를 LINQ to SQL로 쿼리하고 결과를 ToDoItems라는 ToDoItem 개체의 ObservableCollection에 배치합니다. 지연 실행 때문에 ToDoItems 컬렉션을 인스턴스화할 때까지 데이터베이스 쿼리가 실제로 실행되지 않습니다.

// Define query to gather all of the to-do items.
var toDoItemsInDB = from ToDoItem todo in toDoDB.ToDoItems
                    select todo;

// Execute query and place results into a collection.
ToDoItems = new ObservableCollection<ToDoItem>(toDoItemsInDB);

데이터 삽입

데이터베이스에 데이터를 삽입하는 과정은 두 단계로 이루어집니다. 먼저 데이터 컨텍스트에 개체를 추가한 다음 데이터 컨텍스트 SubmitChanges 메서드를 호출하여 데이터를 데이터베이스의 행으로 유지합니다. 자세한 내용은 방법: 데이터베이스에 행 삽입(LINQ to SQL)을 참조하십시오.

다음 예제에서는 ToDoItem 개체를 만들어 ToDoItems 관찰 가능 컬렉션과 toDoDB라는 데이터 컨텍스트의 해당 데이터베이스 테이블에 추가합니다.

// Create a new to-do item based on text box.
ToDoItem newToDo = new ToDoItem { ItemName = newToDoTextBox.Text };

// Add the to-do item to the observable collection.
ToDoItems.Add(newToDo);
            
// Add the to-do item to the local database.
toDoDB.ToDoItems.InsertOnSubmit(newToDo); 

중요중요:

SubmitChanges 메서드를 호출할 때까지 데이터가 데이터베이스에 저장되지 않습니다.

데이터 업데이트

로컬 데이터베이스의 데이터를 업데이트하는 과정은 세 단계로 이루어집니다. 먼저 데이터베이스에서 업데이트할 개체를 쿼리합니다. 개체를 원하는 대로 수정합니다. 마지막으로, SubmitChanges 메서드를 호출하여 로컬 데이터베이스에 변경 사항을 저장합니다. 자세한 내용은 방법: 데이터베이스의 행 업데이트(LINQ to SQL)를 참조하십시오.

데이터 컨텍스트의 개체를 페이지의 컨트롤에 바인딩하면 데이터 컨텍스트가 사용자 상호 작용에 따라 자동으로 업데이트될 수 있습니다. 이 경우 원하는 시간에 SubmitChanges 메서드를 호출하기만 하면 됩니다. 이 방법의 예제는 방법: Windows Phone용 기본 로컬 데이터베이스 응용프로그램 만들기에 설명된 로컬 데이터베이스 예제 응용프로그램에 나와 있습니다. 다음 코드 예제에서는 사용자가 페이지를 벗어난 다른 부분을 탐색할 때 SubmitChanges 메서드를 호출하는 예를 보여 줍니다.

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{ 
    //Call base method
    base.OnNavigatedFrom(e);
            
    //Save changes to the database
    toDoDB.SubmitChanges();
}
중요중요:

SubmitChanges 메서드를 호출할 때까지 데이터베이스의 데이터가 업데이트되지 않습니다.

데이터 삭제

데이터베이스에서 데이터를 삭제하는 과정도 세 단계로 이루어집니다. 먼저 데이터베이스에서 삭제할 개체를 쿼리합니다. 삭제할 개체가 한 개인지 또는 여러 개인지에 따라 DeleteOnSubmit 또는 DeleteAllOnSubmit 메서드를 각각 호출하여 해당 개체를 삭제 보류 중 상태로 전환합니다. 마지막으로, SubmitChanges 메서드를 호출하여 로컬 데이터베이스에 변경 사항을 저장합니다. 자세한 내용은 방법: 데이터베이스에서 행 삭제(LINQ to SQL)를 참조하십시오.

다음 예제에서는 toDoDB라는 데이터베이스에서 ToDoItem 개체를 삭제합니다. 하나의 개체만 삭제하므로 SubmitChanges 전에 DeleteOnSubmit 메서드를 호출합니다.

//Get a handle for the to-do item bound to the button
ToDoItem toDoForDelete = button.DataContext as ToDoItem;

//Remove the to-do item from the observable collection
ToDoItems.Remove(toDoForDelete);

//Remove the to-do item from the local database
toDoDB.ToDoItems.DeleteOnSubmit(toDoForDelete);

//Save changes to the database
toDoDB.SubmitChanges();

중요중요:

SubmitChanges 메서드를 호출할 때까지 데이터베이스에서 데이터가 삭제되지 않습니다.

Windows Phone 응용프로그램을 변경하기 위해 로컬 데이터베이스 스키마를 변경해야 할 수도 있습니다. 로컬 데이터베이스 스키마 변경은 해당 데이터 컨텍스트의 개체 모델 변경으로 시작됩니다. Microsoft.Phone.Data.Linq 네임스페이스는 데이터베이스 스키마 변경에 유용한 DatabaseSchemaUpdater 클래스를 제공합니다. 이 클래스를 사용하는 방법의 예는 연습: Windows Phone의 로컬 데이터베이스 응용프로그램 업데이트를 참조하십시오.

DatabaseSchemaUpdater 클래스는 테이블, 열, 인덱스 또는 연결 추가 등의 추가 변경 작업을 데이터베이스에 수행할 수 있습니다. 더 복잡한 변경 작업의 경우 필요에 따라 새 데이터베이스를 만들고 데이터를 새 스키마로 복사해야 합니다. DatabaseSchemaUpdater 클래스는 데이터베이스의 여러 버전을 프로그래밍 방식으로 구분하는 데 사용할 수 있는 DatabaseSchemaVersion 속성을 제공합니다.

중요중요:

Execute 메서드를 호출할 때까지 데이터베이스가 DatabaseSchemaUpdater 개체의 업데이트를 반영하여 변경되지 않습니다. 이 메서드를 호출하면 버전 업데이트를 포함하여 모든 변경 사항이 로컬 데이터베이스에 단일 트랜잭션으로 전송됩니다. 단일 트랜잭션을 사용하면 사용자가 업그레이드 도중 응용프로그램을 종료하는 경우 등에서 데이터베이스 무결성을 유지하는 데 도움이 됩니다.

다음 예제에서는 DatabaseSchemaUpdater 클래스를 사용하여 DatabaseSchemaVersion 속성에 따라 데이터베이스를 수정하는 과정을 보여 줍니다.

using (ToDoDataContext db = new ToDoDataContext(("isostore:/ToDo.sdf")))
{
        //Create the database schema updater
        DatabaseSchemaUpdater dbUpdate = db.CreateDatabaseSchemaUpdater();

        //Get database version
        int dbVersion = dbUpdate.DatabaseSchemaVersion;

        //Update database as applicable
        if (dbVersion < 5)
        {   //Copy data from existing database to new database 
            MigrateDatabaseToLatestVersion();
        }
        else if (dbVersion == 5)
        {   //Add column to existing database to match the data context
            dbUpdate.AddColumn<ToDoItem>("TaskURL");
            dbUpdate.DatabaseSchemaVersion = 6;
            dbUpdate.Execute();
        }
}

참고참고:

응용프로그램을 업데이트하는 동안 로컬 데이터베이스 파일을 포함하여 격리된 저장소에 저장된 파일은 변경되지 않습니다.

로컬 데이터베이스는 데이터베이스 보안에 유용한 비밀번호 보호 및 암호화 기능을 제공합니다. 데이터베이스에 비밀번호를 사용하면 전체 데이터베이스가 암호화됩니다. 데이터베이스를 암호화하려면 데이터베이스를 만들기 전에 데이터베이스 연결 문자열(데이터 컨텍스트 생성자)에 비밀번호를 제공합니다. 데이터베이스에 액세스할 때마다 비밀번호를 제공해야 합니다. 데이터베이스가 생성된 후에는 데이터베이스를 암호화할 수 없습니다. 데이터베이스는 AES-128을 사용하여 암호화되고 비밀번호는 SHA-256을 사용하여 해시됩니다.

다음 예제에서는 데이터베이스 연결 문자열에 비밀번호를 지정하여 암호화된 데이터베이스를 만드는 과정을 보여 줍니다.

// Create the data context, specify the database file location and password
ToDoDataContext db = new ToDoDataContext ("Data Source=’isostore:/ToDo.sdf’;Password=’securepassword’");

// Create an encrypted database after confirming that it does not exist
if (!db.DatabaseExists()) db.CreateDatabase();

팁팁:

제한된 개수의 인덱싱되지 않은 열만 암호화해야 하는 경우 전체 데이터베이스를 암호화하는 대신 데이터베이스에 데이터를 추가하기 전에 데이터를 암호화하면 성능이 향상될 수 있습니다. 데이터 암호화에 대한 자세한 내용은 방법: Windows Phone 응용프로그램에서 데이터 암호화를 참조하십시오.

로컬 데이터베이스에서 연결 문자열을 사용하는 방법에 대한 자세한 내용은 Windows Phone의 로컬 데이터베이스 연결 문자열을 참조하십시오.

Microsoft는 MSDN 웹 사이트에 대한 귀하의 의견을 이해하기 위해 온라인 설문 조사를 진행하고 있습니다. 참여하도록 선택하시면 MSDN 웹 사이트에서 나가실 때 온라인 설문 조사가 표시됩니다.

참여하시겠습니까?
표시:
© 2015 Microsoft