覆盖 DLL 中的 DataModel

Overriding a DataModel inside a DLL

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

假设我创建了一个使用 CMS 的 DLL 的新项目,尽管客户需要根据其他条件向模型添加新的 tables,什么是覆盖EcomerceModel.edmx 这样我就可以使用新添加的 table 而无需触及新创建项目中的原始 Dll。

谢谢,

你的问题不是一个简单的问题。您要求在编程级别上进行数据映射,并且取决于您想要进行多少更改 overcome/handle 将决定答案必须有多复杂。这也可以看作是模型继承。

首先,edmx 文件对您要执行的操作毫无用处。它将业务模型与数据模型结合在一起,这意味着对数据或业务模型的任何更改都会导致文件损坏。

以下两个选项都需要大量工作,就大小而言应被视为全新的应用程序。

元数据解决方案

您可能想看看在您的代码中创建一个 metadata/data 层并使用它来更改数据库的外观。

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

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

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, Id, "Id", int, "UserId", 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 文件查看扩展的 tables.

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

如果您想做一些研究,请查看使用

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

狩猎好!

嗯,有一个快速的解决方案,就是将您的 Data 项目分成几个项目,以保持最低要求。

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

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

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

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

之后,在您的 Data.Core 中,您将需要引用所有其他 Data.* class 库。然后,您可以像这样创建 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 的新 class 来扩展它。像 :

public class ECommerceCMSContext : ECommerceDbContext 
{
    /// New Entities 
    

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

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

P.S。你可以看一下ASP.NET Core Identity他们正在使用类似的实现,这对你的工作很有帮助。