2013-04-02 4 views
0

데이터를 다시 데이터베이스로 전달하는 클라이언트 측 응용 프로그램을 개발 중입니다. 클라이언트는 PlaylistItem 유형의 객체를 생성 할 수 있습니다. PlaylistItem을 만들 때 데이터베이스가 생성 된 ID로 응답하는 것을 기다리지 않습니다. 대신, 나는 클라이언트가 ID를 생성하게하지만 {PlaylistID, PlaylistItemID}의 PK로 데이터베이스에 PlaylistItem을 작성합니다. PlaylistID는 서버에 의해 생성됩니다. I followed this approach after talking things over a bit with Jon Skeet클라이언트 생성 ID 인 PK는 상위 키가있는 복합 키입니다. NHibernate는 행복하지 않다. 대안?

이제, 나는 NHibernate에서 일하는 것을 얻으려고 노력하고 있지만 꽤 심각한 문제가 있습니다. 내가 읽은 모든 자료는 "NHibernate는 합성 키의 사용에 대해 크게 반대합니다. 레거시 DB에서 작업 할 때만 사용하십시오." 난 레거시 DB에서 일하고 있지 않다. 그래서 나는 변화를해야한다고 생각한다. 그러나, 나는 그러한 대안에서 나의 대안이 무엇인지 모릅니다.

여기 PlaylistItem의 NHibernate에 매핑 및 해당 클래스의 ". = N 백작이 SqlParameterCollection에 대한 잘못된 인덱스 N"

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Streamus" namespace="Streamus.Backend.Domain"> 

    <class name="PlaylistItem" table="[PlaylistItems]" lazy="false" > 
    <composite-id> 
     <key-property name="Id" /> 
     <key-property name="PlaylistId"/> 
    </composite-id> 

    <property name="Title" not-null="true" /> 

    <many-to-one name="Playlist" column="PlaylistId"/> 
    </class> 

</hibernate-mapping> 

[DataContract] 
public class PlaylistItem 
{ 
    [DataMember(Name = "playlistId")] 
    public Guid PlaylistId 
    { 
     get { return Playlist.Id; } 
     set { Playlist.Id = value; } 
    } 

    public Playlist Playlist { get; set; } 

    [DataMember(Name = "id")] 
    public Guid Id { get; set; } 

    // Store Title on PlaylistItem as well as on Video because user might want to rename PlaylistItem. 
    [DataMember(Name = "title")] 
    public string Title { get; set; } 

    public PlaylistItem() 
    { 
     // Id shall be generated by the client. This is OK because it is composite key with 
     // PlaylistId which is generated by the server. 
     Id = Guid.Empty; 
     Title = string.Empty; 
    } 

    private int? _oldHashCode; 
    public override int GetHashCode() 
    { 
     // Once we have a hash code we'll never change it 
     if (_oldHashCode.HasValue) 
      return _oldHashCode.Value; 

     bool thisIsTransient = Equals(Id, Guid.Empty); 

     // When this instance is transient, we use the base GetHashCode() 
     // and remember it, so an instance can NEVER change its hash code. 
     if (thisIsTransient) 
     { 
      _oldHashCode = base.GetHashCode(); 
      return _oldHashCode.Value; 
     } 
     return Id.GetHashCode(); 
    } 

    public override bool Equals(object obj) 
    { 
     PlaylistItem other = obj as PlaylistItem; 
     if (other == null) 
      return false; 

     // handle the case of comparing two NEW objects 
     bool otherIsTransient = Equals(other.Id, Guid.Empty); 
     bool thisIsTransient = Equals(Id, Guid.Empty); 
     if (otherIsTransient && thisIsTransient) 
      return ReferenceEquals(other, this); 

     return other.Id.Equals(Id); 
    } 
} 

NHibernate에 오류 메시지와 함께 예외가 발생합니다 hbm.xml 파일에 중복 된 선언이있을 때 발생하는 것으로 알고 있습니다. 필자는 PlaylistId를 키 속성으로 정의하고 다시 다 대일 관계로 정의하므로이 점이 이해할 수 있습니다.

내 옵션에는 어떤 것들이 있습니까? 나는 꽤 난처한 처지이다.

+0

서버가 성공적으로 삽입 될 때까지 기다리는 것을 원하십니까? 클라이언트는 서버를 기다리지 않고 작업 할 수 있어야하지만 클라이언트 측에서 생성 한 ID 만 신뢰해서는 안된다는 것도 이해합니다. 나는 서버가 클라이언트가 사용할 수있는 유효한 ID들을 묶어서 보내고 서버가 사용 된 키가 유효하다는 것을 확인하도록 고려하고 있지만 NHibernate는 저장이 Create 또는 Update인지를 알 수 없다. ID는 항상 설정 될 것입니다 ... –

+0

나는 그 문제를 해결할 것 같지 않습니다. "GetPlaylistItemByClientID"라고 말하면 클라이언트가 PK인지 또는 값을 고유하게 식별하는 데 사용되는 다른 열에 관계없이 UUID를 생성하는 클라이언트 인 경우 "GetPlaylistItemByPKID"를 말한 것과 동일한 문제입니다. 데이터베이스에서 클라이언트 측에서 생성 한 값의 고유성에 의존 할 수는 없습니다. 맞습니까? –

+0

클라이언트 ID가 고유한지 확인하기 위해 서버에 AJAX 요청을 발행하면 클라이언트가 응답하기 전에 서버의 확인을 기다려야합니다. 이것은 서버가 ID를 생성 할 때까지 기다리는 것과 같습니다. 어쩌면 데이터베이스 저장을 기다릴 필요가 없기 때문에 더 빨라질 수도 있지만 모든 대기 시간은 서버가주고받는 메시지가 아닌 서버로 /부터 전달되는 메시지에서 비롯됩니다. –

답변

1

당신은 ... 즉

<class name="PlaylistItem" table="[PlaylistItems]" lazy="false" > 
    <composite-id> 
    <key-property name="Id" /> 
    <key-many-to-one name="Playlist" column="PlaylistId"/> 
    </composite-id> 

    <property name="Title" not-null="true" /> 

</class> 

그런 다음 클래스의 모습하는 key-many-to-one 대신 key-property으로 사용할 수

[DataContract] 
public class PlaylistItem 
{ 
    // Your composite key... 
    [DataMember(Name = "id")] 
    public Guid Id { get; set; }  
    public Playlist Playlist { get; set; } 

    // Store Title on PlaylistItem as well as on Video because user might want to rename PlaylistItem. 
    [DataMember(Name = "title")] 
    public string Title { get; set; } 

    // rest of class... 
} 
내가하지 않을 때 나는 "클라이언트에게 코드를 제공"할 수 방법
+0

감사합니다 penfold. 감사합니다. –

+0

기꺼이 도와 드리겠습니다. – mickfold