由于我不太了解的原因,我选择不使用 ORM 框架并使用通用的 ADO.NET 数据访问层。我最初创建了一个数据库类,我的所有控制器都可以从中访问。正如除我之外的任何人所预料的那样,这个访问对象已经变成了一个怪物。
为了重构我的数据层,我创建了一个“数据库适配器”类作为 DI 注入服务,并创建了一个“服务层”来使用它。所以现在每个控制器都有一个“域服务”,它将使用数据库适配器来查询数据库并返回一个通用数据表。然后,该服务将填充查询结果并将域对象返回给控制器,在那里它可以组装视图模型。
我遇到了一个问题,我似乎无法抽象设计用于映射从数据库访问层返回的数据集的代码,因为每个查询都可能选择不同的字段。例如,一个简单的参考数据服务:
public class ReferenceDataService : IReferenceDataService
{
private IDatabaseAdapter _dbAdapter;
public ReferenceDataService(IDatabaseAdapter dbAdapter)
{
_dbAdapter = dbAdapter;
}
public IEnumerable<ReferenceData> GetReferenceData(string table)
{
List<ReferenceData> rdList = new List<ReferenceData>();
StringBuilder sb = new StringBuilder();
sb.Append("SELECT [CODE], [LABEL] FROM [dbo].");
sb.Append(table);
sb.Append(" WHERE END_DATETIME > GETDATE()");
DataSet ds = _dbAdapter.ExecuteDataSet(sb.ToString(), null);
foreach (DataRow row in ds.Tables[0].Rows)
{
rdList.Add(PopulateRecord(row));
}
return rdList;
}
private ReferenceData PopulateRecord(DataRow row)
{
return new ReferenceData
{
ReferenceId = (int)row["REFERENCE_ID"],
Code = (string)row["CODE"],
Label = (string)row["LABEL"],
Description = (string)row["DESCRIPTION"],
BeginDatetime = (DateTime)row["BEGIN_DATETIME"],
EndDatetime = (DateTime)row["END_DATETIME"],
UpdatedBy = (string)row["UPDATED_BY"],
UpdatedOn = (DateTime)row["UPDATED_ON"],
CreatedBy = (string)row["CREATED_BY"],
CreatedOn = (DateTime)row["CREATED_ON"]
};
}
}
在这个例子中,我从 populate 方法中抛出了一个异常,因为正如你所看到的,我只是为这个特定的方法选择代码和标签。我想避免每个方法的自定义映射,但我也不想不必要地将每个表行中的所有数据返回到控制器。我想保持 populate 方法的通用性,以便对该表的任何查询都将被适当地映射。
我意识到我基本上几乎是在推出自己的 ORM,但我想使用没有它的服务模式,因为在这一点上我太投入了。