当我使用两个不同的生成的linq代码时,如何实现Rob Conery在[MVC Storefront] [1]中显示的所谓“存储库模式”?我是否需要实现真正的存储库模式,正如Fredrik Normen在What purpose does the Repository Pattern have?讨论的那样?问题是我希望传递LINQ从我的“存储库”提供的一些很好的功能,以便我以后可以使用它,所以如果不需要,我不想像Fredrik讨论的那样实现真正的存储库模式。
现在我的问题。我已经下载了[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
}
答案 0 :(得分:1)
这有点偏离,但可能有所帮助。
如果您正在使用Linq,存储库,MySql和MS Sql以及Rob Connery的建议,您可以使用SubSonic 3并让您的生活更轻松。
这是一个5分钟的演示:http://subsonicproject.com/docs/Simple_Repo_5_Minute_Demo
答案 1 :(得分: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文件。
答案 2 :(得分:0)
我和你的情况相同,我正在使用Linq-to-SQL,但将来我想尝试Entity Framework,我会这样做。
对于我所看到的,解决方案是使用依赖注入和ioc容器(如果你不使用它,看看,看起来很难但很容易和有趣)。
大多数示例为每个存储库创建一个接口,然后使用ioc配置文件,您可以选择要使用的内容。
例如,您有一个ICustomersRepository
,这是您可能在控制器中使用的,SQLCustomersRepository
和EntityCustomersRepository
,您只能更改配置文件。
正如您所说的问题是具有相同名称的实体......解决方案是对实体使用相同的模式,为每个实体创建一个接口并使用ioc容器。我知道这是tedius,我要做的是创建一个T4模板,自动为每个实体创建接口,然后替换T4模板,使用LinqToSQL和entiy Framework实现它...是的很多工作。
有关T4的介绍,请查看此视频, http://msdn.microsoft.com/en-us/vstudio/cc308634.aspx
答案 3 :(得分:0)
我建议你的BO实体命名空间,例如MyCompany.MyApp.Entities。
然后,您可以更改每个DBML的Entity Namespace属性,以在其中生成您的实体。如果您对同一类型使用多个DBML,则需要为每个DBML都有一个单独的命名空间,例如MyCompany.MyApp.Entities.MySql)
如果您需要预先安排多种类型的数据库/数据访问平台的类,我建议您创建实体可以具体化的抽象基类,以及用于进行数据访问的抽象存储库。
根据我自己的经验,我最近创建了一个抽象的LinqToSqlRepostory,然后将其扩展为我的主要业务对象。