2009-07-23 1 views
2

Как я могу реализовать так называемый «шаблон репозитория», который показывает Rob Conery в [MVC Storefront] [1], когда я использую два разных сгенерированных кода linq? Нужно ли мне реализовать реальный шаблон репозитория, как обсуждает Фредрик Нормен на What purpose does the Repository Pattern have?? Дело в том, что я хочу передать некоторые из приятных функций, которые LINQ предоставляет из моего «репозитория», чтобы впоследствии использовать его, поэтому, если это не требуется, я не хочу реализовывать реальный шаблон репозитория, о котором говорил Фредрик.Образец репозитория с использованием linq

Теперь к моей проблеме. Я загрузил [dblinq] [3], который является поставщиком Linq для MySql, Oracle и PostgreSQL. В моем проекте я создал код LINQ для MySQL и SQL (Microsoft). Проблема в том, что им нужно создавать классы с одинаковыми именами, но с несколько иным контентом. Могу ли я каким-то образом реализовать это с пространством имен или чем-то, чтобы я мог использовать их оба, как и идея с «шаблоном репозитория»? Пример таблицы языка 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, а также советы Роба Коннери, вы можете использовать SubSonic 3 и сделать вашу жизнь немного легче.

Вот 5 минут демо: http://subsonicproject.com/docs/Simple_Repo_5_Minute_Demo

+0

Благодарим вас за ответ. SubSonic действительно выглядит многообещающим. Но я хочу узнать больше о .net, прежде чем начать использовать что-то вроде этого (я только что пробовал .net в течение одной недели). – unkownt

0

Я нахожусь в такой же ситуации, как вы, я использую Linq к SQL, но в будущем я хочу попробовать Entity Framework, и я буду делать ,

Для того, что я увидел, решение этого - использование инъекции зависимостей и контейнера ioc (если вы его не используете, посмотрите, может показаться сложным, но очень легким и интересным).

Большинство примеров этого, создает интерфейс для каждого репозитория, а затем с помощью файла конфигурации ioc вы можете выбрать, что вы хотите использовать.

Например, у вас есть ICustomersRepository, то есть то, что вы можете использовать в ваших контроллерах и SQLCustomersRepository и EntityCustomersRepository, что вы можете поменять местами только изменения файла конфигурации.

Как вы сказали, проблема заключается в объектах с тем же именем ... решение состоит в том, чтобы использовать один и тот же шаблон для сущностей, создать интерфейс для каждого объекта и использовать контейнер ioc. Я знаю, что это tedius, то, что я сделал бы, это создать шаблон T4, который автоматически создает интерфейсы для каждого объекта, а затем заменяет шаблоны T4, которые используют LinqToSQL и Entiy Framework для его реализации ... да, это большая работа.

Для введения Т4 посмотрите на это видео, http://msdn.microsoft.com/en-us/vstudio/cc308634.aspx

0

Я хотел бы предложить пространство имен сущностей для BO, например MyCompany.MyApp.Entities.

Затем вы можете изменить свойство пространства имен Entity для каждого DBML, чтобы сгенерировать в нем объекты. Если вы используете более одного DBML для тех же типов, вам нужно будет иметь отдельное пространство имен для каждого DBML, например MyCompany.MyApp.Entities.MySql)

Если вам нужны классы для более чем одного типа платформы базы данных/доступа к данным, я предлагаю вам создавать абстрактные базовые классы, которые могут быть созданы вашими сущностями, и абстрактный репозиторий для доступа к данным.

В моем собственном опыте я недавно создал абстрактный LinqToSqlRepostory, а затем расширил его для своих основных бизнес-объектов.