简体   繁体   English

MongoDb和实体框架的抽象

[英]Abstraction over MongoDb and Entity Framework

I might be on mission impossible, due to this quote by Mark Seemann : 由于Mark Seemann的引用,我可能无法完成任务:

If you have a specific ORM in mind, then be explicit about it. 如果您有一个特定的ORM,那么请明确它。 Don't hide it behind an interface. 不要将其隐藏在界面后面。 It creates the illusion that you can replace one implementation with another. 它会产生一种幻觉,即您可以将一种实现替换为另一种实现。 In practice, that's impossible. 在实践中,这是不可能的。

But what I am trying to accomplish is to switch my Entity Framework ORM out with the MongoDb driver just by changing my dependencies on startup. 但我想要完成的是通过改变我在启动时的依赖关系来切换我的实体框架ORM与MongoDb驱动程序。

But I keep running into problems where I do not offer enough flexibility or simply having too many new NotImplementedException(); 但我一直遇到问题,我没有提供足够的灵活性或只是有太多new NotImplementedException(); in my MongoDb implementation. 在我的MongoDb实现中。

My interfaces current structure is looking like this: 我的接口当前结构如下所示:

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;
}

But already by this implementation I can not do the "complete" MongoDb implementation, since MongoDb does not utilize the unit-of-work pattern, or two-phase commit. 但是已经通过这个实现我不能做“完整的”MongoDb实现,因为MongoDb不使用工作单元模式或两阶段提交。

I then thought of moving the IUnitOfWork into extensions methods of the IWriteEntities , but then I loose my DbContext which is wired onto the Entity Framework implementation and I wont use a service-locator pattern in a static method. 那么我想移动的IUnitOfWork到的扩展方法IWriteEntities ,但后来我失去我DbContext这是有线到实体框架的实施和我在一个静态方法不会使用服务定位器模式。

So my last resort, is to ask if there is any golden path I have not yet tried? 所以我的最后一招,是问我有没有尝试过的黄金道路? Or I should simple create two more interfaces: 或者我应该简单地创建另外两个接口:

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

public interface IMongoDbWriter : IWriteEntities {}

And use these in my application. 并在我的应用程序中使用它们。 But then again, this is not what I planned on. 但话说回来,这不是我的计划。 Any feedback is appreciated. 任何反馈都表示赞赏。

Head explosing 头探索

switch my Entity Framework ORM out with the MongoDb driver just by changing my dependencies on startup. 只需在启动时更改我的依赖项,就可以使用MongoDb驱动程序切换我的实体框架ORM。

This goes far deeper than the mere problem of interfaces . 这比接口的单纯问题要深刻得多。 This will result in a cataclysmic clash of philosophies. 这将导致哲学的灾难性冲突。

MongoDB should be used with somewhat write-heavy, often de-normalized data structures. MongoDB应该使用一些写重,通常是非规范化的数据结构。 Your indexes, inserts and workers are complicated, and the queries are trivial. 您的索引,插入和工作人员很复杂,查询很简单。 The schema must be carefully designed to support the queries you'll need, not based on the relation between the objects. 必须仔细设计架构以支持您需要的查询, 而不是基于对象之间的关系。

The classical SQL approach is reverse: The relationships alone are enough to come up with a good data structure, the schema is trivial (albeit large) there are no workers for eventual consistency, but the queries are insanely complex, usually because things that belong together must be split across two or three tables. 经典的SQL方法是相反的:单独的关系足以提供一个良好的数据结构,模式是微不足道的(尽管很大)没有工人可以实现最终的一致性,但查询非常复杂,通常是因为属于一起的东西必须分成两个或三个表。 This is why Transaction and Unit of Work are key in a typical SQL-environment, while they're not even supported in MongoDB. 这就是为什么事务和工作单元是典型SQL环境中的关键,而MongoDB甚至不支持它们。

Of course, I'm simplifying: There's a spectrum here, and you can abuse both MongoDB and RDBMSes as simple key-value stores; 当然,我正在简化:这里有一个频谱,你可以滥用MongoDB和RDBMSes作为简单的键值存储; you can come up with a de-normalized data structure in SQL, and you can keep a ton of relations in MongoDB. 你可以在SQL中提出一个非规范化的数据结构,你可以在MongoDB中保持大量的关系。 But your MongoDB won't learn referential integrity or (distributed) transactions and your SQL Server won't let go of SQL. 但是你的MongoDB不会学习参照完整性或(分布式)事务,你的SQL Server也不会放弃SQL。

But the more abstractions you use and the broader support they have, the more will you hide these key principles behind a bloated mess of code. 但是你使用的抽象越多,它们拥有更广泛的支持,你就会越多地隐藏这些臃肿的代码背后的关键原则。 I think one can generally say: An interface that is abstract enough can be implemented by any technology, but it frustrates the user. 我认为通常可以说:足够抽象的界面可以通过任何技术实现,但它会让用户感到沮丧。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM