2009-07-23 4 views
2

두 개의 다른 생성 된 linq 코드를 사용할 때 Rob Conery가 [MVC Storefront] [1]에서 보여주는 소위 "리포지토리 패턴"을 어떻게 구현할 수 있습니까? Fredrik Normen이 What purpose does the Repository Pattern have?에 토론 할 때 실제 저장소 패턴을 구현해야합니까? 문제는 LINQ가 내 "저장소"에서 제공하는 멋진 기능 중 일부를 전달하여 나중에 사용할 수 있기 때문에 필요하지 않은 경우 Fredrik에서 논의한 실제 저장소 패턴을 구현하고 싶지 않다는 것입니다.리포지터리 패턴 linq 사용

내 문제가 있습니다. 나는 [dblinq] [3]을 다운로드 받았는데, 이것은 MySQL, Oracle, PostgreSQL을위한 Linq Provider이다. 내 프로젝트에서 나는 MySQL과 SQL (마이크로 소프트)을위한 LINQ 코드를 생성했다. 문제는 둘 다 이름이 같지만 내용이 약간 다른 클래스를 생성해야한다는 것입니다. 어떻게 든 이것을 "네임 스페이스"또는 "무엇"으로 구현하여 "저장소 패턴"과 같은 아이디어를 사용할 수 있습니까? 언어 테이블 SQL

[Table(Name="dbo.Language")] 
public partial class Language : INotifyPropertyChanging, INotifyPropertyChanged 
{ 

    private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); 

    private int _Id; 

    private string _Name; 

    private EntitySet<Book> _Books; 

#region Extensibility Method Definitions 
partial void OnLoaded(); 
partial void OnValidate(System.Data.Linq.ChangeAction action); 
partial void OnCreated(); 
partial void OnIdChanging(int value); 
partial void OnIdChanged(); 
partial void OnNameChanging(string value); 
partial void OnNameChanged(); 
#endregion 

    public Language() 
    { 
     this._Books = new EntitySet<Book>(new Action<Book>(this.attach_Books), new Action<Book>(this.detach_Books)); 
     OnCreated(); 
    } 

    [Column(Storage="_Id", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)] 
    public int Id 
    { 
     get 
     { 
      return this._Id; 
     } 
     set 
     { 
      if ((this._Id != value)) 
      { 
       this.OnIdChanging(value); 
       this.SendPropertyChanging(); 
       this._Id = value; 
       this.SendPropertyChanged("Id"); 
       this.OnIdChanged(); 
      } 
     } 
    } 

    [Column(Storage="_Name", DbType="NVarChar(100) NOT NULL", CanBeNull=false)] 
    public string Name 
    { 
     get 
     { 
      return this._Name; 
     } 
     set 
     { 
      if ((this._Name != value)) 
      { 
       this.OnNameChanging(value); 
       this.SendPropertyChanging(); 
       this._Name = value; 
       this.SendPropertyChanged("Name"); 
       this.OnNameChanged(); 
      } 
     } 
    } 

    [Association(Name="Language_Book", Storage="_Books", ThisKey="Id", OtherKey="Language")] 
    public EntitySet<Book> Books 
    { 
     get 
     { 
      return this._Books; 
     } 
     set 
     { 
      this._Books.Assign(value); 
     } 
    } 

    public event PropertyChangingEventHandler PropertyChanging; 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void SendPropertyChanging() 
    { 
     if ((this.PropertyChanging != null)) 
     { 
      this.PropertyChanging(this, emptyChangingEventArgs); 
     } 
    } 

    protected virtual void SendPropertyChanged(String propertyName) 
    { 
     if ((this.PropertyChanged != null)) 
     { 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    private void attach_Books(Book entity) 
    { 
     this.SendPropertyChanging(); 
     entity.Language1 = this; 
    } 

    private void detach_Books(Book entity) 
    { 
     this.SendPropertyChanging(); 
     entity.Language1 = null; 
    } 
} 

MySQL의

[Table(Name = "asp.Language")] 
public partial class Language : INotifyPropertyChanged 
{ 
    #region INotifyPropertyChanged handling 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    #endregion 

    #region int ID 

    private int _id; 
    [DebuggerNonUserCode] 
    [Column(Storage = "_id", Name = "Id", DbType = "int", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false)] 
    public int ID 
    { 
     get 
     { 
      return _id; 
     } 
     set 
     { 
      if (value != _id) 
      { 
       _id = value; 
       OnPropertyChanged("ID"); 
      } 
     } 
    } 

    #endregion 

    #region string Name 

    private string _name; 
    [DebuggerNonUserCode] 
    [Column(Storage = "_name", Name = "Name", DbType = "varchar(100)", CanBeNull = false)] 
    public string Name 
    { 
     get 
     { 
      return _name; 
     } 
     set 
     { 
      if (value != _name) 
      { 
       _name = value; 
       OnPropertyChanged("Name"); 
      } 
     } 
    } 

    #endregion 

    #region Children 

    private EntitySet<Book> _book; 
    [Association(Storage = "_book", OtherKey = "Language", ThisKey = "ID", Name = "Book_ibfk_1")] 
    [DebuggerNonUserCode] 
    public EntitySet<Book> Book 
    { 
     get 
     { 
      return _book; 
     } 
     set 
     { 
      _book = value; 
     } 
    } 


    #endregion 

    #region Attachement handlers 

    private void Book_Attach(Book entity) 
    { 
     entity.LanguageLanguage = this; 
    } 

    private void Book_Detach(Book entity) 
    { 
     entity.LanguageLanguage = null; 
    } 


    #endregion 

    #region ctor 

    public Language() 
    { 
     _book = new EntitySet<Book>(Book_Attach, Book_Detach); 
    } 

    #endregion 

} 

답변

1

이상적으로는 각 클래스를 한 번만 만들면 데이터베이스 차이점을 ORM에서 처리해야합니다 (NHibernate 및 Subsonic 작동 방식).

각 데이터베이스마다 실제로 다른 클래스가 필요한 경우 은 다른 이름 공간 인에 있으면 이름이 같은 클래스를 가질 수 있습니다. 당신이 클래스에 대한 코드를 작성하는 경우 자신이 매우 쉽습니다 : 클래스가 자동으로 생성되는 경우, 네임 스페이스를 지정하는 방법을 코드 생성 도구에서 확인해야

// C# sample 
namespace MyCompany.MyApp.Entities.Oracle 
{ 
    public class MyClass 
    { 
    // ... 
    } 
} 

namespace MyCompany.MyApp.Entities.SqlServer 
{ 
    public class MyClass 
    { 
    // ... 
    } 
} 

. 예를 들어, LINQ to SQL 디자이너를 사용하면 테이블/클래스 속성에서 네임 스페이스를 지정하거나 직접 DBML 파일을 편집 할 수 있습니다.

1

에 대한 예이 조금 논외이지만 도움이 될 수 있습니다.

Linq, 리포지토리, MySql 및 MS Sql 및 Rob Connery의 조언을 사용하는 경우 SubSonic 3을 사용하고 좀 더 쉽게 사용할 수 있습니다. 여기

은 5 분 데모입니다 : 당신이, 내가 Linq에-에-SQL 사용하고 나는이 같은 상황에서 오전 http://subsonicproject.com/docs/Simple_Repo_5_Minute_Demo

+0

답변 해 주셔서 감사합니다. SubSonic은 실제로 유망 해 보입니다. 그러나 나는 그와 같은 것을 사용하기 전에 .net에 대해 더 많이 배우고 싶다. (나는 지금 일주일 동안 .net을 시도했다.) – unkownt

0

하지만, 미래에 내가 엔티티 프레임 워크를 시도하려는, 내가 할 것 .

내가 본 것에 대한 해결책은 사용 종속성 주입과 ioc 컨테이너 (사용하지 않으면 열심히 보일 수 있지만 매우 쉽고 흥미 롭습니다.)입니다.

대부분의 예제는 각 저장소에 대한 인터페이스를 작성한 후 ioc 구성 파일을 사용하여 무엇을 사용할지 선택할 수 있습니다.

예를 들어 컨트롤러에 사용할 수있는 주소는 ICustomersRepository이고 구성 파일 만 바꿀 수있는 주소는 SQLCustomersRepositoryEntityCustomersRepository입니다.

문제는 동일한 이름을 가진 엔티티입니다 ... 해결 방법은 엔티티에 대해 동일한 패턴을 사용하고 각 엔티티에 대한 인터페이스를 만들고 ioc 컨테이너를 사용하는 것입니다. 나는 이것이 tedius다는 것을 알고, T4 템플릿을 생성하여 각 엔티티에 대한 인터페이스를 자동으로 생성 한 다음 LinqToSQL과 entiy 프레임 워크를 사용하여 T4 템플릿을 교체하는 것입니다. 그렇습니다. 많은 작업이 필요합니다. T4의 소개는

http://msdn.microsoft.com/en-us/vstudio/cc308634.aspx

0

나는 같은 MyCompany.MyApp.Entities로, 당신의 BO에 대한 엔티티 네임 스페이스를 제안,이 비디오를보십시오.

그런 다음 각 DBML의 Entity Namespace 속성을 변경하여 여기에서 엔티티를 생성 할 수 있습니다. 동일한 유형에 대해 둘 이상의 DBML을 사용하는 경우 MyCompany.MyApp.Entities와 같이 각 DBML에 대해 별도의 네임 스페이스가 있어야합니다.MySql)

데이터베이스/데이터 액세스 플랫폼의 여러 유형에 대한 클래스가 필요한 경우 엔티티에서 구체화 할 수있는 추상 기본 클래스를 만들고 데이터 액세스를 수행하는 추상 리포지토리를 만드는 것이 좋습니다.

내 자신의 경험에 나는 최근에 추상적 인 LinqToSqlRepostory를 만든 다음 이것을 주요 비즈니스 개체로 확장했습니다.