1

我收到了几十条旧 SQL 语句,每条语句都有数百行。Models每个 SQL 都映射到共享项目中具有自己唯一 POCO 的代码。

例如项目中的 SQLSelect Name, Birthday From People有一个等价的 POCO Models

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库在整个应用程序中使用,并且我不希望 SQL 在该 HardcodedSql 属性中的应用程序中公开。

这是我正在使用的架构:

Suamere的领域

4

3 回答 3

1

简单的解决方案是制作HardcodedSql internal而不是public只在 DAL 项目中可见。如果 DAL 是一个独立于模型的项目,您可以使用InternalsVisibleTo它来将其公开给该项目。这假设您可以相应地配置您的项目结构。

于 2014-11-10T16:38:22.300 回答
1

首先,您必须将您的模型(即 POCO)与实际属于 DAL 的 SQL 分开。控制反转是做到这一点的正确方法。IRepository<MyPOCO>最好在 IoC 容器中注册从抽象存储库(例如)到包含 SQL 的实现的映射,而不是通用 sql 运行器。

编辑:更具体地说,一个可能的解决方案:

  • 将所有 SQL 放置到 DAL 内的单独文件中,例如放置到一组具有名称约定的嵌入式资源文件,例如 Legacy-{0}.sql,其中 {0} 是 POCO 的名称。
  • 创建使用 POCO 名称作为键并从资源集中选择相应的 Legacy-{0}.sql 文件的旧存储库的通用实现。请注意,可能还有其他实现使用其他数据访问技术,例如 ORM。
  • 在组合根目录中明确地注册了从遗留 POCO 到遗留实现的所有IRepository<MyPOCO1> => LegacyRepo<MyPOCO1>; IRepository<MyPOCO2> => LegacyRepo<MyPOCO2>; etc映射: . 此外,您可以注册从非传统实体到存储库的其他实现的其他映射。
于 2014-11-10T21:00:31.187 回答
1

我建议也许有两种可能的方式来处理这个问题。

至于第一种方法,我宁愿改变sql的访问方式,将调用本地包装在一个方法中。所以这个类可能有一个名为 public IEnumerable GetFromSql() 的函数,你可以在上下文中传递,或者创建一个新的,我不确定你是如何在你的项目中设置 EF 的。这样您就永远不会公开暴露原始 sql,因为您可能宁愿将其设为私有变量或局部常量,而只需从函数内部访问它。

作为第二种选择,我实际上已经这样做了,结果非常好,我是否将所有 sql 移动到视图并使用 EF 访问它们。这样我的代码中就没有 sql 污染。看到模型已经存在,调用视图的结果将与您已有的类型相匹配。

于 2014-11-10T17:36:07.647 回答