- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在设计 n 层应用程序时,我倾向于使用采用并改编自 Lhotka 的 CSLA 框架的模式。简而言之,Repository 层填充一个 SqlDataReader 并将数据读取器、要映射的实例和映射信息传递给 Mapper 层,然后 Mapper 层填充该实例。
由于多种原因,这种模式在我从事的许多项目中一次又一次地证明了自己:
这里是一些示例存储库代码:
internal static List<CompositeEntities.ContactReportRpa> RetrieveByReportId(int reportId)
{
CompositeEntities.ContactReportRpa report = null;
List<CompositeEntities.ContactReportRpa> reports = new List<CompositeEntities.ContactReportRpa>();
using (SqlConnection conn = DBConnection.GetConnection())
{
cmd.Connection = conn;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "ContactReportRpa_SEL_ByIdReport";
cmd.Parameters.Add("@IdReport", System.Data.SqlDbType.Int).Value = reportId;
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
report = new CompositeEntities.ContactReportRpa();
ContactReportRpaMapper.Map("IdReportRpa", "IdReport", "IdRecommendation", "IsDisplayed", "Comments", report.Rpa, reader);
RpaRecommendationMapper.Map("IdRecommendation", "IdDepartment", "TitleRecommendation", "Description", "DisplayOrderRecommendation", report.Recommendation, reader);
RpaDepartmentMapper.Map("IdDepartment", "TitleDepartment", "DisplayOrderDepartment", report.Department, reader);
reports.Add(report);
}
}
}
return reports;
}
这是一些示例映射器代码。这非常简单:映射器知道哪个类属性被映射到数据读取器中的每个字段。每个字段的名称都传递给映射器,因此无论分配给存储过程中每个字段的名称如何,都可以使用相同的映射器。
internal static void Map(string fieldId, string fieldName, string fieldDisplayOrder, RpaDepartment entity, SqlDataReader reader)
{
entity.Id = reader.GetInt32(reader.GetOrdinal(fieldId));
entity.Title = reader.GetString(reader.GetOrdinal(fieldName));
entity.DisplayOrder = reader.GetInt32(reader.GetOrdinal(fieldDisplayOrder));
}
所以我的问题是:当数据源是文本文件时,我应该如何实现这种模式?我想坚持这种模式,因为最终数据源将迁移到数据库。
有什么建议吗?
编辑:ini 文件已经存在,此时我无法继续更改它们。所以我现在坚持使用它们。
最佳答案
在 ini 文件中创建良好的数据层次结构有点困难。这就是 MS 似乎主要迁移到 XML 文件的部分原因。查看此问题的答案:Reading/writing an INI file
如果您选择 XML 选项,我将跳过这些映射内容,并在使用 XPath 找到合适的 XML 后直接将您的对象序列化。那么您就不需要映射器了。
你也可以选择 an in-memory or file-based DB, like SqLite . Perf 会很棒,而且您的部署占用空间非常小。
另外,我建议避免尝试抽象这个映射器的东西,因为我认为它不能很好地在 DB 和 ini 文件之间转换。如果你看看那里许多 ORM 库的复杂性,你就会发现这种映射真的有多么困难。映射级别的大多数概念根本无法很好地转换为 ini 文件。将映射(存储库)的是更高级别的概念,这就是我发布原始答案的原因(见下文)。
但是如果你想保持你正在使用的模式,你的 ini 文件看起来像这样:
[Report.3]
IdReport = 3
IdReportRpas = 7,13
[ReportRpa.7]
IdReportRpa = 7
IdReport = 3
IdRecommendation = 12
IsDisplayed = true
Comments = I'm not sure what an RPA is...
[ReportRpa.13]
IdReportRpa = 13
IdReport = 3
; ... and rest of properties here
[Recommendation.12]
IdRecommendation = 12
IdDepartment = 33
TitleRecommendation = Some Recommendation
Description = Some Recommendation Description
DisplayOrderRecommendation = 0
[Department.33]
IdDepartment = 33
TitleDepartment = Bureau of DBs and ini files
DisplayOrderDepartment = 0
...然后您可以简单地编写您的存储库以从 ini 部分获取数据,并编写您的映射器来查看每个 ini 值,就像您当前查看结果集中的列一样。
using(var iniFileReader = new IniFileReader())
{
string reportSectionName = string.Format("Report.{0}", contactId);
var reportSection = iniFileReader.GetSection(reportSectionName);
// Todo: Abstract this sort of procedure/enumeration stuff out.
// Similar to the existing code's stored procedure call
int[] idReportRpas = reportSection.GetValue(IdReportRpas)
.Split(',')
.Select(s => int.Parse(s);
foreach(string idReportRpa in idReportRpas)
{
report = new CompositeEntities.ContactReportRpa();
string rpaSectionName = string.Format("ReportRpa.{0}", idReportRpa);
var rpaSection = iniFileReader.GetSection(rpaSectionName);
ContactReportRpaMapper.Map("IdReportRpa", "IdReport", "IdRecommendation",
"IsDisplayed", "Comments", report.Rpa, rpaSection);
// ...
}
}
您当前的映射器代码绑定(bind)到您的存储类型,因此您需要提出一个更通用的映射器接口(interface)。或者使最后一个 reader 参数更通用以支持两种映射类型(在您的情况下,reader
,在我的情况下,每个 ini 部分实例)。例如:
public interface IDataValueReader
{
// Signature is one that might be able to support ini files:
// string -> string; then cast
//
// As well as a DB reader:
// string -> strongly typed object
T ReadValue<T>(string valueName);
}
public class DbDataReader : IDataValueReader
{
private readonly SqlDataReader reader;
public DbDataReader(SqlDataReader reader)
{
this.reader = reader;
}
object ReadValue<T>(string fieldId)
{
return (T)reader.GetObject(reader.GetOrdinal(fieldId));
}
}
public class IniDataSectionReader : IDataValueReader
{
private readonly IniFileSection fileSection;
public IniDataSectionReader(IniFileSection fileSection)
{
this.fileSection = fileSection;
}
object ReadValue<T>(string valueName)
{
return (T)Convert.ChangeType(fileSection.GetValue(fieldId), typeof(T));
}
}
请注意,这都是自定义代码 - 没有官方的 ini 文件阅读器,我也没有尝试过,所以我无法就使用哪个第三方库提出建议。 That question I linked at the top有一些建议。
(部分内容可能还有用)
为你的 repository 创建一个接口(interface)
,并确保您的代码的更高层仅通过此接口(interface)与您的数据存储对话。
示例界面(您的可能不同):
public interface IReportRepository
{
void Create(Report report);
Report Read(int id);
void Update(Report report);
void Delete(Report report);
}
如果需要,您也可以使该接口(interface)通用。
为了确保更高层只知道存储库,您可以在IReportRepository
的实现中构建与文件/数据库对话的类,或使用Dependency Injection填充它。但是无论您做什么,除了IRepository
和您的个人数据实体(Report
)之外,不要让您的更高级别的代码知道任何信息。
您可能还想查看 the Unit of Work pattern ,并在那里包装实际的数据访问。这样您就可以轻松支持 transactional semantics ,以及缓冲/惰性存储访问(即使是文件)。
对于您的示例实现,SqlConnection
和 SqlDataReader
将位于您的工作单元类中,映射代码和特定存储过程名称可能位于每个存储库中类。
让这个结构完全独立地工作可能有点棘手,但如果你看一下 Microsoft Entity Framework 生成的代码,它们实际上有它们的工作单元类实例化每个存储库,你只需像访问它一样访问它属性(property)。大致是这样的:
public interface IUnitOfWork : IDisposable
{
void CommitChanges();
void RollbackChanges();
}
public class MyDataModel : IUnitOfWork
{
private bool isDisposed;
private readonly SqlConnection sqlConnection;
public MyDataModel()
{
sqlConnection = DBConnection.GetConnection();
}
// Todo: Implement IUnitOfWork here
public void Dispose()
{
sqlConnection.Dispose();
isDisposed = true;
}
public IRepository<Report> Reports
{
get
{
return new ReportDbRepository(sqlConnection);
}
}
}
public class ReportDbRepository : IRepository<Report>
{
private readonly SqlConnection sqlConnection;
public ReportDbRepository(SqlConnection sqlConnection)
{
this.sqlConnection = sqlConnection;
}
// Todo: Implement IRepository<Report> here using sqlConnection
}
有用的阅读:
关于c# - 对于存储在 ini 文件中的信息,什么是好的 Mapper 模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7640315/
from sqlalchemy import * from sqlalchemy import create_engine, ForeignKey from sqlalchemy import Col
我使用 MR1 API(hadoop-core-1.2.1.jar) 编写了一个示例字数统计程序。映射器类定义如下, public interface Mapper extends JobConfi
创建maven项目,修改pom.xml文件,如下: ? 1
问题最终得到解决在底部查看我的解决方案 最近我正在尝试运行 Mahout in Action 的第 6 章( list 6.1 ~ 6.4)中的推荐系统示例。但是我遇到了一个问题,我已经用谷歌搜索了但
如果有人知道在 .NET 中执行此操作的更多方法,您对这些方法有何看法?您选择哪种方法,为什么? 下面是.NET中对象拷贝不同方式的测试。 与此原始线程相关的测试:How to copy value
我能看出参数个数的不同,但我不知道实现上的不同。 每种方法的行为是否存在重要差异? 最佳答案 第一个填充您传入的现有对象。第二个为您创建一个新对象。这是“项目”和“填充”之间的语义差异。 关于c# -
我正在将一个项目从 Glass Mapper v2 (Glass.Mapper.Sitecore) 升级到 v4 (Glass.Mapper.Sc),我遇到了一个问题,我们的解决方案是使用 Insta
我正在实现一些 hadoop 应用程序。我的编码部分几乎完成了。但是想在阅读“Lin & Chris Dryer”的映射器设计模式书后改进编码器。至于这种方法的有效实现,需要在 map 函数中保留状态
当我尝试访问该页面时发生此错误。我在创建表时没有遇到错误,但似乎仍然存在问题。 模型是这样的: class User(UserMixin, db.Model): id = db.Column(
我创建了一个使用 SQLAlchemy 的类: class DbAbsLayer(object): def __init__(self): self.setConnection
我试图在我的 MVC - Sitecore - 7.1 中的 v4.0.30319 项目中使用 Glass Mapper。 以下是我安装的 Glass Mapper 版本 Glass Mapper 版
我在尝试使用 org.apache.hadoop.mapred.lib.IdentityMapper 作为 Hadoop Streaming 1.0.3 中 -mapper 的参数时遇到了问题。 “猫
这是我的mybatis配置。这是我的pom.xml。。当我运行项目时,它显示了错误的原因:org/mybatis/spring/mapper/MapperScannerConfigurer.有没有人能
背景: 1.在数据库中有一个通知表 可以看到其中的 gmt_create、 notifier_name、 outer_title 这三个字段是有下划线的 2.这张表
hadoop配置对象仅允许在set方法中将字符串作为值 set(字符串名称,字符串值) 是否有一种简单的方法来设置任何其他对象类型?我想在映射器中检索这些对象。 我注意到在0.15左右的版本中,有一个
我要开发的更大目标如下: a)仪表板,除其他功能外,用户还可以上传文档(.pdf,.txt,.doc)。所有这些文档都转到特定目录。 b)用户还可以查询所有带有特定关键字标记的文档。 现在,我希望使用
2016-10-20 18:03:51.253 WARN 17216 --- [restartedMain] .s.c.a.CommonAnnotationBeanPostProcessor:在名为“
我正在尝试同时使用映射器和缩减器来运行作业,但映射器运行缓慢.. 如果对于相同的输入我禁用 reducers,映射器将在 3 分钟内完成而对于 mapper-reducer 作业,即使在 30 分钟后
由于一些数据在所有 map() 函数之间共享,我无法在 setup() 中生成它们,因为每个 setup() 对应于每个map() 函数,而我想做的是预先生成一些数据并将其存储在可实现的地方,然后在每
我正在使用 Hadoop,我想使用静态变量来减少必须进行的方法调用次数。以下是我如何使用静力学: public class Mapper extends Mapper { protected
我是一名优秀的程序员,十分优秀!