覆盖 DLL 中的数据模型

问题描述

我正在开发一个新的 MVC 项目,它基本上是一个我打算在其他项目中使用的 CMS,结构如下

enter image description here

假设我创建了一个使用我的 CMS 的 DLL 的新项目,尽管客户需要根据附加条件向模型添加一个新表,那么覆盖 EcomerceModel.edmx 的最佳方法是什么,以便我可以工作使用新添加的表,而无需接触新创建的项目中的原始 Dll。

谢谢,

解决方法

嗯,对此有一个快速的解决方案,即将您的 Data 项目划分为多个项目,以使其保持在最低要求。

因此,如果我们以您的 Data 项目为例,它将被分成几个类库,例如:

  • Data.Models(仅包含用于抽象目的的数据模型)。​​
  • Data.Core(主要数据项目)。
  • Data.Common(可选)
  • Data.Helpers(可选)

为了使这可能起作用,您需要切换到 Code First 方法,以确保您可以控制您的迁移和模型。 (您不需要 EF 在每次更新模型时覆盖您的自定义设置,而且您需要将更新保留在代码中而不是数据库中)。

建议将您的模型保存在单独的程序集中,以便在其他项目中重复使用,而无需引用完整的数据层。

此后,在您的 Data.Core 中,您需要将所有其他 Data.* 类库引用到它。然后,您可以像这样创建您的 DbContext

public class ECommerceDbContext : DbContext 
{
    public DbSet<Admin> Admins { get; set; }
    
    /// rest of Entities 
    

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        
        // your Entities configurations 
    }   
}

现在,您的 Data 层已设置并准备好在其他项目中引用。

在您想要重用当前 Data.Core 的其他项目中,您需要引用 Data.Core(通过项目引用或 Nuget)。然后,创建一个继承 ECommerceDbContext 的新类来扩展它。类似的东西:

public class ECommerceCMSContext : ECommerceDbContext 
{
    /// New Entities 
    

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        
        // New Entities configurations 
    }   
}

现在,使用 ECommerceCMSContext 将任何新表添加到当前上下文中。

附言您可以查看ASP.NET Core Identity他们使用的类似实现,这对您的工作非常有帮助。

,

你的问题不容易回答。您要求在程序级别上进行数据映射,并且取决于您想要克服/处理的更改量将决定答案的复杂程度。这也可以看作是模型继承。

首先,edmx 文件对于您想做的事情没有用。它将业务模型与数据模型相结合,这意味着对数据或业务模型的任何更改都会导致文件损坏。

以下两个选项都需要大量工作,并且在大小方面应被视为全新的应用程序。

元数据解决方案

您可能希望在代码中创建元数据/数据层,并使用它来更改数据库的外观。

不是通过 ecommerce.edmx 访问模型 - 通过单独的业务/数据层访问它。然后,数据层可以使用动态调用或使用外部首选项文件来保存 sql 访问来创建数据访问/sql。

即 使用描述要使用的表的元数据在代码中创建外部文件、数据库中的表或资源。一个非常简单的解决方案可能如下所示:

MetaTables (id,myTableName,derivedTableName)
    Order,"Order","UserOrder"
    Customer,"Customer","UserCustomer"

MetaAttributes (tableId,id,myAttrName,myAttrType,derivedAttrName,derivedType,etc)
    Order,Id,"Id",int,"UserId",guid
    Order,Description,"Description",string,"UserDescription",string
    Customer,guid

MetaRelations ()
    etc

然后使用它来动态创建您的查询。如果你这样做,其他人可以使用你的代码,只需要用新的映射更新你的元数据文件。只要他们不添加新的必填列。

优势:

  • 可以快速处理任何新的数据结构
  • 如果需要,可以动态更改数据结构
  • 独立于版本

弱点:

  • 动态创建的查询可能非常慢
  • 实现动态数据层需要很长时间

反射解决方案

另一种方法是将数据层存储在单独的程序集中并使用接口引用它。

新应用程序需要做的就是用他们的数据层替换您的数据层。

public interface IDataLayer
{
    public List<IOrder> GetOrderList()
}

// MyDLL1
public class DataLayerImplementationA: IDataLayer
{
    public List<IOrder> GetOrderList()
    {
        // get data from database X,return results
    }
}

// MyDLL2
public class DataLayerImplementationB: IDataLayer
{
    public List<IOrder> GetOrderList()
    {
        // get data from database B,return results
    }
}

优势:

  • 代码旨在与新数据库配合使用
  • 最快的实施
  • 编译时检查!

弱点:

  • 需要使用新编译的 DLL 覆盖程序集
  • 多个 DLL
  • 即使是很小的更改也可能需要程序员进行大量编码(或至少是剪切和粘贴)

解决办法

如果修改非常简单,您可以编写一个解析器来编辑 edmx 文件中的映射数据。不推荐,因为这可能会导致不稳定。

另一种解决方法可能包括使用数据库视图来隐藏更改并将数据更改处理移至数据库。因此,请让旧的 edmx 文件查看视图,并将扩展设计的新 edmx 文件查看扩展表。

变通办法就是......除了最微不足道的变化之外,它们可能会比它们的价值更痛苦。

如果您想做一些研究,请查看使用类似术语的文章

  • 面向对象的概念
  • 抽象数据层
  • 模型继承
  • 模型控制器视图

狩猎好!

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...