我得到了几十个遗留的SQL语句,每行数百行。在共享的Models
项目中,每个SQL都映射到具有自己唯一POCO的代码。
例如,SQL Select Name, Birthday From People
在Models
项目中具有等效POCO:
public class BirthdayPerson : SqlResultBase {
public string Name { get; set; }
public datetime Birthday { get; set; }
//SqlResultBase abstraction:
public string HardcodedSql { get {
return "Select Name, Birthday From People";
}}
}
在我的DAL中,我有一个单个通用SQL运行器,其<T>
代表SQL的POCO。所以我的业务逻辑可以调用GetSqlResult<BirthdayPerson>()
:
public IEnumerable<T> GetSqlResult<T>() where T : SqlResultBase, new() {
return context.Database.SqlQuery<T>((new T()).HardcodedSql);
}
问题是我的Models
库在整个应用程序中使用,我不希望在该HardcodedSql属性中跨应用程序公开SQL。
这是我正在使用的架构:
答案 0 :(得分:1)
最简单的解决方案是制作HardcodedSql
internal
而不是public
,因此它只能在DAL项目中显示。如果DAL是与模型分开的项目,则可以使用InternalsVisibleTo
将其公开给该项目。这假设您可以相应地配置项目结构。
答案 1 :(得分:1)
我建议可能有两种方法来处理这个问题。
至于第一种方法,我宁愿改变访问sql的方式,并在方法中本地包装调用。因此,类可能有一个名为public IEnumerable GetFromSql()的函数,您可以在上下文中传递,或者创建一个新函数,我不确定您是如何在项目中设置EF的。这样你就不会公开地暴露原始的sql,因为你宁愿把它变成私有变量或局部常量,也许只是从函数中访问它。
作为第二个选项,我实际上已经完成了这个并且结果非常好,我将所有sql移动到视图并使用EF来访问它们。这样我的代码就没有sql污染了。 看到模型已经存在,调用视图的结果将与您已有的类型相匹配。
答案 2 :(得分:1)
首先,您必须将模型(即POCO)与实际属于DAL的SQL分开。控制反转是正确的方法。而不是通用的sql runner,最好在IoC容器中注册从抽象存储库(例如IRepository<MyPOCO>
)到包含SQL的实现的映射。
编辑:更具体一点,一个可能的解决方案:
IRepository<MyPOCO1> => LegacyRepo<MyPOCO1>; IRepository<MyPOCO2> => LegacyRepo<MyPOCO2>; etc
。此外,您可以将其他映射从非遗留实体注册到其他存储库实现。