【问题标题】:Abstraction over MongoDb and Entity Framework对 MongoDb 和实体框架的抽象
【发布时间】:2015-05-05 02:02:09
【问题描述】:

由于Mark Seemann 的这句话,我可能正在完成一项不可能完成的任务:

如果您有特定的 ORM,请明确说明。别 将其隐藏在界面后面。它创造了一种错觉,你可以 用另一种实现替换。在实践中,这是 不可能的。

但我想要完成的是通过更改我在启动时的依赖项来使用 MongoDb 驱动程序切换我的实体框架 ORM。

但我一直遇到一些问题,即我没有提供足够的灵活性,或者只是在我的 MongoDb 实现中拥有太多 new NotImplementedException();

我的接口当前结构如下所示:

public interface IReadEntities
{
    IQueryable<TEntity> Query<TEntity>() where TEntity : Entity;
}

public interface IWriteEntities : IUnitOfWork, IReadEntities
{
    TEntity Get<TEntity>(object firstKeyValue, params object[] otherKeyValues) where TEntity : Entity;

    Task<TEntity> GetAsync<TEntity>(object firstKeyValue, params object[] otherKeyValues) where TEntity : Entity;

    IQueryable<TEntity> Get<TEntity>() where TEntity : Entity;

    void Create<TEntity>(TEntity entity) where TEntity : Entity;

    void Delete<TEntity>(TEntity entity) where TEntity : Entity;

    void Update<TEntity>(TEntity entity) where TEntity : Entity;
}

public interface IUnitOfWork
{
    int SaveChanges();

    Task<int> SaveChangesAsync();

    Task DiscardChangesAsync();

    void DiscardChanges();

    void Reload<TEntity>(TEntity entity) where TEntity : Entity;

    Task ReloadAsync<TEntity>(TEntity entity) where TEntity : Entity;
}

但是通过这个实现,我已经无法完成“完整”的 MongoDb 实现,因为 MongoDb 不使用工作单元模式或两阶段提交。

然后我想将IUnitOfWork 移动到IWriteEntities 的扩展方法中,但后来我失去了连接到实体框架实现的DbContext,我不会在静态方法中使用服务定位器模式.

所以我最后的手段,就是问有没有我还没有尝试过的黄金之路?或者我应该简单地再创建两个接口:

public interface IEntityFrameworkWriter : IWriteEntities, IUnitOfWork {} // Move IUnitOfWork out of IWriteEntities

public interface IMongoDbWriter : IWriteEntities {}

并在我的应用程序中使用这些。但话又说回来,这不是我计划的。感谢您提供任何反馈。

爆头

【问题讨论】:

    标签: c# entity-framework mongodb dependency-injection abstraction


    【解决方案1】:

    只需更改启动时的依赖项,即可使用 MongoDb 驱动程序切换我的实体框架 ORM。

    这比单纯的接口问题要深入得多。这将导致一场灾难性的哲学冲突。

    MongoDB 应该与写入量较大、通常是非规范化的数据结构一起使用。您的索引、插入和工作程序很复杂,查询也很简单。架构必须经过精心设计以支持您需要的查询,而不是基于对象之间的关系。

    经典的 SQL 方法是相反的:仅靠关系就足以产生良好的数据结构,架构很简单(尽管很大),没有用于最终一致性的工作人员,但是查询非常复杂,通常是因为属于一起的必须拆分到两个或三个表中。这就是为什么事务和工作单元是典型 SQL 环境中的关键,而 MongoDB 甚至不支持它们。

    当然,我是在简化:这里有一个范围,您可以将 MongoDB 和 RDBMS 都用作简单的键值存储;您可以在 SQL 中提出非规范化的数据结构,并且可以在 MongoDB 中保留大量关系。但是您的 MongoDB 不会学习参照完整性或(分布式)事务,并且您的 SQL Server 不会放弃 SQL。

    但是,您使用的抽象越多,它们获得的支持越广泛,您就越会将这些关键原则隐藏在臃肿的代码后面。我想一般可以这么说:一个足够抽象的接口,任何技术都可以实现,但它会让用户感到沮丧。

    【讨论】:

    • 美丽的答案。如果您正在谈论将 MongoDB 实现隐藏在您自己的接口后面,以便稍后您可以通过切换适配器将其替换为另一个 NoSQL 数据库,同时保持相同的查询原则,我会完全理解但将您的 MongoDB 调用隐藏在典型的关系后面界面会给你和你的用户带来很多痛苦,会引入很多很多的错误,并且可能会迫使你以从未打算使用的方式使用 MongoDB,并且可能会引入性能和可用性限制。
    • 也许我会使用关系抽象(EF、NHibernate 等)和 NoSql 抽象。这样做的主要原因是我正在创建一个“简单”的框架,我想在 CQRS 环境中支持 NoSql 和开箱即用的 Sql。
    • 我会挑战目标本身:如果框架应该是“简单的”,这不与换出 sql 与 nosql 的要求相矛盾吗?此外,NoSQL 解决方案的创建并不相同:适用于 MongoDB 的方法根本不适用于 redis,反之亦然。 NoSQL 的想法是为特定工作使用最好的工具,该工具的权衡与您的问题相匹配...如果您将旧的工具重新应用于所有工作习惯用法...我猜不会有太大收获。
    • 是的,归根结底就是这样。我的论点是,无论抽象是什么,您的依赖都存在,因为它体现在您的数据模型中,甚至可能体现在用户概念中
    • 也许是我摆脱所有抽象的时候了,只需在 EF 上创建一些辅助扩展方法,并为IMongoCollection&lt;T&gt; 创建一些辅助扩展方法。感谢您的洞察力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多