분류

C# 및 동적 유형으로 스키마를 스택 위로 이동하지 않기

카우치베이스 서버 2.0 작업의 중요한 이점 중 하나는 유연한 스키마입니다. 문서는 JSON으로 저장되므로 서로 순서를 강요하지 않는 암시적 구조의 레코드가 가능합니다. 실제 세계에서 이러한 '암시적 구조'는 애플리케이션에서 비롯됩니다. 애플리케이션에서 새 사용자를 만들면 연결된 문서는 도메인 개체의 JSON 직렬화된 버전입니다.

public 클래스 사용자
{
    [JsonIgnore]
    public 문자열 Id { get; set; }
   
    [제이슨 프로퍼티("username")]
    public 문자열 사용자 이름 { get; set; }
   
    [제이슨 프로퍼티("비밀번호")]
    public 문자열 비밀번호 { get; set; }
   
    [제이슨 프로퍼티("type")]
    public 문자열 유형 { get { 반환 "user"; } }
}

//저장됨 { "사용자 이름" : "hmoody", "비밀번호" : "b3cca" }로 저장됩니다.

이 접근 방식은 잘 정의된 도메인 객체에서 문서를 읽고 쓰는 애플리케이션에서 일반적이지만, 문서 구조가 의도적으로 잘 정의되지 않은 경우도 있습니다. 이러한 경우에는 문서 유형별로 도메인 객체를 사용하는 것이 적합하지 않을 수 있습니다. 

파이썬이나 루비 같은 언어에서는 덜 객체 지향적인 접근 방식(예: 사전이나 해시)을 사용하는 것이 일반적일 수 있지만, C#나 Java 같은 강력한 타입의 언어에서는 강력한 타입의 데이터 객체, 흔히 플레인 올드(Java|C#) 객체를 사용하여 애플리케이션 데이터를 표현하는 것이 훨씬 더 일반적입니다. 하지만 이러한 언어에서도 동적 언어 접근 방식을 사용할 수 있습니다. 

최근 사용자가 다음과 같은 질문을 했을 때 스택오버플로우에서 에서 JSON 문서를 Couchbase에서 느슨하게 입력된 C# 객체로 가져오는 방법에 대해 설명하면서 두 가지 옵션을 제안했습니다. 이 글의 나머지 부분에서는 데이터에 비슷한 접근 방식을 취하는 데 사용할 수 있는 몇 가지 기본적인 확장 방법에 대해 설명하겠습니다.

첫 번째 접근 방식은 사전 인스턴스입니다. 사전은 JSON 구조에 자연스럽게 매핑되므로 덜 구조화된 방식으로 문서를 작업할 때 자연스럽게 선택할 수 있습니다. 중첩된 사전은 복잡한 JSON 구조에도 잘 매핑됩니다. 

var user1 = new 사전<문자열, 객체>
{
    { "username", "jzablocki" },
    { "환경설정", new 사전<문자열, 객체>
        {
            { "theme",  "green"},
            { "시간대",  "EST" }
        }
    }
};

이 문서를 저장하고 읽기 위해 사전을 저장하고 검색하는 확장 메서드를 추가하겠습니다. 이러한 메서드는 새로운 정적 클래스인 카우치베이스 동적 확장.

public 정적 클래스 카우치베이스 동적 확장 { ... }

첫 번째 방법은 단순히 표준 ExecuteStore 메서드와 비슷하지만 몇 가지를 캡슐화합니다. 먼저, Newtonsoft.JSON 라이브러리를 사용하여 사전을 JSON으로 직렬화하는 작업을 처리합니다. 직렬화기 설정을 수정하여 낙타 대소문자 또는 기타 JSON 형식화 옵션을 지원할 수 있습니다. 기본값은 그대로 두었습니다. 두 번째로, 제가 캡슐화한 IStoreOperationResponse 의 세부 정보를 더 간단한 튜플 반환으로 변경했습니다. 튜플은 일반적으로 동적 언어에서 반환되며, 저는 좀 더 동적으로 만들려고 노력하고 있기 때문에 이것이 적절한 접근 방식인 것 같았습니다.

public 정적 튜플<bool, int, 문자열> 스토어사전( ICouchbaseClient 클라이언트, 저장소 모드 저장소 모드,
                                            문자열 키, 사전<문자열, 객체> 사전)
{
    var json = JsonConvert.SerializeObject(사전);
    var 결과 = 클라이언트.ExecuteStore(storeMode, key, json);

    만약 (!결과.성공)
    {
        만약 (결과.예외 != null) throw 결과.예외;

        반환 튜플.만들기(false결과.상태 코드.HasValue ? 결과.상태 코드.가치 : -1결과.메시지);
    }

    반환 튜플.만들기(true, 0, 문자열.비어 있음);
}

저장된 JSON에서 사전을 다시 가져오는 것은 단순히 프로세스를 역전시키는 것입니다. 다시 말하지만, IGetOperationResult를 Tuple로 래핑하고 저장된 JSON을 사전 인스턴스입니다.

public 정적 튜플<bool, int, 문자열, 사전<문자열, 객체>> GetDictionary( ICouchbaseClient 클라이언트, 문자열)
{
    var 결과 = 클라이언트.ExecuteGet<문자열>();

    만약 (!결과.성공)
    {
        만약 (결과.예외 != null) throw 결과.예외;

        반환 튜플.만들기<bool, int, 문자열, 사전<문자열, 객체>>
                    (false결과.상태 코드.HasValue ? 결과.상태 코드.가치 : -1결과.메시지, null);
    }

    var dict = JsonConvert.역직렬화 개체<사전<문자열, 객체>>(결과.가치);
    반환 튜플.만들기(true, 0, 문자열.비어 있음, 딕트);
}

저장 및 검색은 간단합니다(확장 클래스 네임스페이스에 사용자를 추가해야 합니다).

var 결과 = 클라이언트.스토어사전(스토어모드.설정, "user_1", user1);
만약 (결과.Item1)
{
   var dict = 클라이언트.GetDictionary("user_1").Item4;
   콘솔.WriteLine(dict); //Dictionary.ToString()의 출력이어야 합니다.
}

더 흥미로운 접근 방식은 C#의 새로운 동적 입력 및 ExpandoObject 클래스. 이러한 기능을 통해 개발자는 컴파일 시점이 아닌 런타임에 컴파일러가 형식 검사를 수행하도록 지시할 수 있습니다. JSON 문서 작업은 다이내믹스의 훌륭한 사용 사례입니다.

동적 확장 메서드는 이전에는 사전이 있었다면 이제는 동적 유형이 있다는 점을 제외하면 거의 동일합니다. 

public 정적 튜플<bool, int, 문자열> StoreDynamic( ICouchbaseClient 클라이언트, 저장소 모드 저장소 모드,
                                            문자열 키, ExpandoObject 객체)
{
    var json = JsonConvert.SerializeObject(객체);
    var 결과 = 클라이언트.ExecuteStore(storeMode, key, json);

    만약 (!결과.성공)
    {
        만약 (결과.예외 != null) throw 결과.예외 as 예외;

        반환 튜플.만들기(false결과.상태 코드.HasValue ? 결과.상태 코드.가치 : -1결과.메시지);
    }

    반환 튜플.만들기(true, 0, 문자열.비어 있음);
}

public 정적 튜플<bool, int, 문자열, ExpandoObject> GetDynamic( ICouchbaseClient 클라이언트, 문자열)
{
    var 결과 = 클라이언트.ExecuteGet<문자열>();

    만약 (!결과.성공)
    {
        만약 (결과.예외 != null) throw 결과.예외;

        반환 튜플.만들기<bool, int, 문자열, ExpandoObject>
                    (false결과.상태 코드.HasValue ? 결과.상태 코드.가치 : -1결과.메시지, null);
    }

    var 객체 = JsonConvert.역직렬화 개체<ExpandoObject>(결과.가치);
    반환 튜플.만들기(true, 0, 문자열.비어 있음, 객체);
}

그런 다음 코드에서 동적 인스턴스를 사용하여 Couchbase Server에 데이터를 저장하고 검색할 수 있습니다. 아래 코드 접근 방식을 사용하여 JSON 문서를 ExpandoObject로 읽을 수도 있습니다. 이를 테스트하려면 GetDynamic 키를 "user_1"로 설정합니다.

동적 사용자2 = new ExpandoObject();
user2.사용자 이름 = "jzablocki";
user2.기본 설정 = new ExpandoObject();
user2.기본 설정.테마 = "green";
user2.기본 설정.시간대 = "EST";

클라이언트.StoreDynamic(스토어모드.설정, "user_2", user2 as ExpandoObject);
var getResult = 클라이언트.GetDynamic("user_2");
만약 (getResult.Item1)
{
    동적 항목 = getResult.Item4;
    콘솔.WriteLine(항목.기본 설정.테마);
}

동적 인수를 사용하여 확장 메서드를 호출할 때의 한계로 인해 캐스팅이 필요한 동적 확장에 대한 다른 접근 방식이 있습니다. 간단하게 설명하기 위해 저는 ExpandoObject 인수를 사용합니다. 

C#는 분명히 순수한 동적 언어가 아니므로 일부 메서드는 순수한 후기 바인딩 언어에 비해 덜 간결합니다. 그러나 이러한 메서드들은 언어가 정적으로 입력된다는 이유만으로 스키마 없는 문서 지향 데이터베이스의 풍부한 기능을 포기할 필요가 없다는 것을 보여줍니다(물론 그 언어가 C#인 한)...
이 문서 공유하기
받은 편지함에서 카우치베이스 블로그 업데이트 받기
이 필드는 필수 입력 사항입니다.

작성자

게시자 존 자블로키

존 자블로키는 NET. SDK 개발자입니다. John은 Beantown ALT.NET의 주최자이자 Fairfield University의 전 겸임교수이기도 합니다. Amazon에서 Couchbase Server를 설치하고 구성하는 방법을 설명하는 "Couchbase Essentials"라는 책을 확인할 수도 있습니다.

댓글 하나

  1. 뉴욕 로체스터 이사 11월 27, 2013에서 7:05 오전

    공유해 주셔서 감사합니다...............

  2. 난드키쇼르 잉가발레 5월 13, 2015에서 2:26 오후

    존 매우 유용한 게시물입니다.

댓글 남기기

카우치베이스 카펠라를 시작할 준비가 되셨나요?

구축 시작

개발자 포털에서 NoSQL을 살펴보고, 리소스를 찾아보고, 튜토리얼을 시작하세요.

카펠라 무료 사용

클릭 몇 번으로 Couchbase를 직접 체험해 보세요. Capella DBaaS는 가장 쉽고 빠르게 시작할 수 있는 방법입니다.

연락하기

카우치베이스 제품에 대해 자세히 알고 싶으신가요? 저희가 도와드리겠습니다.