我正在努力提高我的设计模式技巧,我很好奇这些模式之间有什么区别?所有这些看起来都是一样的 - 封装了特定实体的数据库逻辑,因此调用代码不了解底层持久层.从我的简短研究中,他们通常都会实现您的标准CRUD方法并抽象出特定于数据库的详细信息.
除了命名约定(例如CustomerMapper与CustomerDAO vs. CustomerGateway vs. CustomerRepository)之外,有什么区别?如果存在差异,您何时会选择一个而不是另一个?
在过去,我会编写类似于以下的代码(简化,自然 - 我通常不会使用公共属性):
public class Customer
{
public long ID;
public string FirstName;
public string LastName;
public string CompanyName;
}
public interface ICustomerGateway
{
IList<Customer> GetAll();
Customer GetCustomerByID(long id);
bool AddNewCustomer(Customer customer);
bool UpdateCustomer(Customer customer);
bool DeleteCustomer(long id);
}
Run Code Online (Sandbox Code Playgroud)
并有一个CustomerGateway类为所有方法实现特定的数据库逻辑.有时我不会使用接口并使CustomerGateway上的所有方法都是静态的(我知道,我知道,这使得它不太可测试)所以我可以这样称呼它:
Customer cust = CustomerGateway.GetCustomerByID(42);
Run Code Online (Sandbox Code Playgroud)
这似乎与Data Mapper和Repository模式的原理相同; DAO模式(与Gateway相同,我认为?)似乎也鼓励特定于数据库的网关.
我错过了什么吗?有3-4种不同的方式做同样的事情似乎有点奇怪.
我正在使用带有ruby的datamapper将数据存储到某些表中.
有几个表有非常大量的信息,我想在用户"重建数据库"时清除它们(它基本上删除了所有内容并重新计算数据).
我最初尝试使用Forum.all.destroy并为所有不同的表做了它,但我注意到其中一些只是没有从phpmyadmin中删除.我只能想象它因为外键.虽然我真的不知道,因为我的其他表格已成功删除.更不用说,无论如何,它只是'零',所以键不会达到非常大的数字(如#500,000键).
然后我尝试使用下面的代码运行它,但由于"外键约束",它没有清除表格.我想强迫它工作,因为我知道一个事实我正在清理所有相互依赖的表(我只是没有清除2个表,一个设置表和一个随机存储表,两者都没有使用外键).
到目前为止我有......
adapter = DataMapper.repository(:default).adapter
adapter.execute('TRUNCATE TABLE `forums`, `dates`, `remarks`');
Run Code Online (Sandbox Code Playgroud)
这很好,除了mysql语法显然是错误的.所以这是第一件事
我在phpmyadmin中逐一做到这一点,当我这样做的时候,它说
Cannot truncate a table referenced in a foreign key constraint
Run Code Online (Sandbox Code Playgroud) 在大量关于Repository和Data Mapper的阅读之后,我决定在测试项目中实现这些模式.由于我是这些人的新手,我想了解一下如何在一个简单的项目中实现这些.
杰里米·米勒说:
做一些非常重要的个人编码项目,你可以自由地尝试设计模式.
但我不知道我做了所有这些事情是对的.
这是我的项目结构:

正如您所看到的,我将在下面详细介绍它们.
域:项目域实体到这里我有一个简单的Personnel类,它继承自EntityBase类,EntityBase类有一个名为Id的属性.
public int Id { get; set; }
Run Code Online (Sandbox Code Playgroud)Infrustructure:这是一个简单的数据访问层,有两个类.SqlDataLayer是一个简单的类,它继承自名为DataLayer的抽象类.在这里,我提供了以下代码的一些功能:
public SQLDataLayer() {
const string connString = "ConnectionString goes here";
_connection = new SqlConnection(connString);
_command = _connection.CreateCommand();
}
Run Code Online (Sandbox Code Playgroud)添加参数到命令参数集合:
public override void AddParameter(string key, string value) {
var parameter = _command.CreateParameter();
parameter.Value = value;
parameter.ParameterName = key;
_command.Parameters.Add(parameter);
}
Run Code Online (Sandbox Code Playgroud)
执行DataReader:
public override IDataReader ExecuteReader() {
if (_connection.State == ConnectionState.Closed)
_connection.Open();
return _command.ExecuteReader();
}
Run Code Online (Sandbox Code Playgroud)
等等.
IRepository.cs:
public interface IRepository<TEntity> where TEntity : EntityBase
{ …Run Code Online (Sandbox Code Playgroud) 我很好奇你们对DataMapper的看法,以及它对Rails 3中新的和改进的ActiveRecord带来的好处.
我感谢你的意见.
我发现两种模式似乎有相同的目标 - 有什么区别?
我差不多完成了我的数据映射器,但现在我正处于关系的关键时刻.
我会试着在这里说明我的想法.我无法找到关于这个主题的好文章/信息,所以也许我正在重新发明轮子(我确定,我可以使用一个大框架 - 但我想通过这样做来学习).
1:1关系
首先,让我们看一下1:1的关系.通常,当我们有一个名为"Company"的域类和一个名为"Address"的域类时,我们的Company类将具有类似address_id的内容.让我们说在大多数情况下我们只显示公司列表,只有当有人查看详细信息时才需要地址.在这种情况下,我的数据映射器(CompanyDataMapper)只是懒惰加载,这意味着它只从数据库中获取该address_id,但也不会进行连接以获取地址数据.
一般来说,我对每个关系都有一个getter方法.所以在这种情况下,有一个getAddress(Company companyObject)方法.它需要一个公司对象,查找它的地址属性,如果它是NULL,则使用该Address对象的Mapper类(AddressDataMapper)从数据库中提取相应的Address对象,并将该地址对象分配给指定的address属性.公司对象.
重要提示:数据映射器是否允许使用其他数据映射器?
让我们说在大多数情况下,您需要公司对象和地址对象,因为您始终将它一起显示在列表中.在这种情况下,CompanyDataMapper不仅可以获取公司对象,还可以使用JOIN进行SQL查询,以获取地址对象的所有字段.最后,它迭代记录集并使用相应的值提供新对象,将地址对象分配给公司对象.
听起来很简单,到目前为止.
1:n关系
这些怎么样?与1:1的唯一区别在于公司可能有多个Address对象.让我们来看看:当我们大部分时间只对公司感兴趣时,Data Mapper只会将公司对象的addresses属性设置为NULL.addresses属性是一个可以引用无,一个或多个地址的数组.但是我们还不知道,因为我们懒得加载,所以它只是NULL.但是,如果在大多数情况下我们还需要所有地址呢?如果我们要显示包含所有公司及其所有地址的大清单?在这种情况下,事情开始变得非常丑陋.首先,我们不能为每个地址对象加入地址表五十次(我坚信这是不可能的,如果是,性能将低于零).所以,当我们进一步思考这个问题时,在这种情况下不可能懒得加载.
重要提示:这是真的吗?如果我有10个公司,每10个地址,我必须发出100个查询才能获得100个地址对象吗?
m:n关系
让我们说一个地址对象只包含国家,州,城市,道路和门牌号码.但是,一栋房子可能是一座大型商业大厦,其中有很多公司.就像其中一个现代化的办公楼,任何人都可以在其网站上租一个小rom来炫耀那座塔楼.所以:许多公司可以共享相同的地址.
我还没有计划处理这类问题.
重要提示:可能与1:n关系相比,这不是一个更大的问题吗?
如果有人知道有关解决/实现这个问题的详细资源,我会很高兴找到一个链接!
我的一位同事目前正在设计类似下面的SQL查询来生成报告,这些报告通过外部数据查询显示在excel文件中.目前,只需要DB上的报告流程(无CRUD操作).
我试图说服他最好使用ruby ORM以便能够在rails/sinatra应用程序中显示数据.
尽管在显示数据方面有明显的优势,但他在学习使用像Sequel或Datamapper这样的ORM方面有什么优势呢?
他正在编写的SQL查询显然非常复杂,并且对于SQL来说相对较新,他经常抱怨它非常耗时且令人困惑.是否可以使用ORM编写极其复杂的查询?如果是这样,哪个是最合适的(我听说续集对遗留dbs有好处)?在制作复杂的数据库查询时,学习ruby和使用ORM与坚持使用纯SQL有什么好处?
我有我想要加载的实体,以及其他ocassions懒惰(甚至是额外的懒惰)加载.
我的映射没有在我的YAML中声明的获取模式 - 因此它们使用默认值(延迟加载).
目前,热切加载的唯一方法是手动构建DQL - 每次添加新实体时我都需要更新它.
理想情况下,我只是加载根实体和强制加载所有关联对象的力.有什么方法可以做到这一点吗?
如果不是为什么(是否有一个原因超出它是一个未实现的功能)?
我想在Ruby on Rails项目中为我的模型使用一个更独立的系统.看起来解决方案是DataMapper.但是,我看到他们的存储库在去年都没有更新过,当安装在Rails 4项目中时,它与新版Gems的gem版本依赖冲突.使用Rails 4时,搜索不会显示任何内容.
现在的状态是什么?我应该使用它还是别的什么?
ruby ruby-on-rails datamapper ruby-datamapper ruby-on-rails-4
我正在寻找一个Ruby ORM来取代ActiveRecord.我一直在看Sequel和DataMapper.它们看起来很不错,但是它们似乎都不是基本的:当你不需要时,不要将所有内容都加载到内存中.
我的意思是我在ActiveRecord和Sequel上尝试了以下(或等效的)有很多行的表:
posts.each { |p| puts p }
Run Code Online (Sandbox Code Playgroud)
他们两个都记忆犹新.它们似乎将所有内容加载到内存中,而不是在需要时获取内容.我find_in_batches在ActiveRecord中使用了它,但这不是一个可接受的解决方案:
为什么我的代码应该知道分页机制?我很高兴配置页面大小的某个地方,但就是这样.有了find_in_batches你需要做的是这样的:
post.find_in_batches {| batch | batch.each {| p | 把p}}
但这应该是透明的.
那么有可靠的Ruby ORM可以正确获取吗?
更新:
正如塞尔吉奥所说,在Rails 3中你可以使用find_each我想要的东西.但是,由于ActiveRecord不是一个选项,除非有人能说服我使用它,所以问题是:
find_each,而find应该这样做,不应该吗?datamapper ×10
ruby ×4
orm ×3
c# ×2
repository ×2
sequel ×2
activerecord ×1
dao ×1
doctrine ×1
doctrine-orm ×1
mysql ×1
oop ×1
sql ×1