如何构建实体框架应用程序(使用 MEF)

本文关键字:应用程序 使用 MEF 框架 实体 构建 何构建 | 更新日期: 2023-09-27 17:56:16

我迫切地想知道如何构建我的实体框架 4(代码优先)应用程序。

我有一个 VS 项目将处理对我的数据的访问。 它是一个基于接口[IDataExport]的MEF导出部分[MyData]。 该项目有我的 EF 类(客户、订单等)、上下文初始值设定项等,以及所有已经像梦一样工作的东西。

有一个 VS 项目,它有我的接口(我所有的接口)。 所有项目都有对此接口项目的引用。

我有一个 VS 项目可以完成我所有的日志记录。 它也是一个基于接口[ILogging]的MEF导出部件[MyLog]。 该类实际上只是写入控制台。

我有三个 VS 项目,我们将它们称为 Parts(以 MEF 术语表示)。 它们是插件。 他们需要数据来工作(客户、订单等)。 实际上,他们需要同时从三个不同的表输入数据作为输入。

我有一个项目是主机应用程序。 它目前作为控制台应用程序运行,但很快就会转换为 Windows 服务。

我希望这能让你对现有的架构有一个很好的了解。 现在我在试图弄清楚如何正确进行数据访问时遇到了麻烦。

当主机需要将数据传递给插件时,它需要从 3 个不同的表中获取数据。 实际上,使用 EF 设置它的方式,将立即检索三个表。 当插件由 MEF 实例化时,如何将该数据传递给插件? 插件是否可以引发事件以与主机应用程序交互?

此外,随着插件的运行,表中的数据将需要更新。 如何将数据库中的数据向上更新三层? 主机可以调用插件,但插件无法调用主机。 只有[MyData]项目才能访问数据库。

根据我描述的场景,有人可以告诉我如何最好地构建此应用程序吗?

更让我困惑的是,一些示例代码显示了调用应用程序(在本例中为主机),为每次搜索调用数据库启动全新的模型。

例如
public List<Customer> FindCustomerList(string companyName)
{
    return new CustomerManager().FindCustomerList(companyName);
}

public List<Customer> FindCustomerList(string companyName)
{
    var q = from c in context.Customers
            where c.CompanyName.StartsWith(companyName)
            select c;
    return q.ToList();
}

下面是我的三个表格。 请注意,它们具有外键关系,导致子项嵌入到主作业记录中。 就像一个有很多订单的客户。

public class pcJobAction : IVersionTracking, IpcIdentity
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public long Id { get; set; }
    //IpcIdentity
    [Required]
    [MaxLength(75)] 
    public string name { get; set; }
    [MaxLength(1000)] 
    public string description { get; set; }
    [Required]
    [MaxLength(30)] 
    public string ServerName { get; set; }
    [MaxLength(20)] 
    public string ServerIP { get; set; }        
    public int JobEnabled { get; set; }
    public virtual ICollection<pcPlugInValue> PlugInText { get; set; }
    //JobActions holds a list of Schedules
    public virtual ICollection<pcJobSchedule> JobSchedules { get; set; }
    //FK to the JobTypes table (Delete Files, Verify Backups, Ping, etc)
    public long pcJobTypeId { get; set; }
    public virtual pcJobType pcJobType { get; set; }
    //IVersionTracking
    public DateTime DateCreated { get; set; }
    public DateTime LastUpdated { get; set; }
    [Timestamp]
    public byte[] Version { get; set; }       
}
public class pcPlugInValue : IVersionTracking, IpcIdentity
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long Id { get; set; }
    //IpcIdentity
    [Required]
    [MaxLength(75)]
    public string name { get; set; }
    [MaxLength(1000)]
    public string description { get; set; }
    public string PlugInText { get; set; }
    public int ExecuteOrder { get; set; }
    //FK to the JobAction table
    public long pcJobActionId { get; set; }
    public virtual pcJobAction pcJobAction { get; set; }
    //FK to the codes table (to indetify the schedule type: daily, weekly, etc)
    public long pcCodeId { get; set; }
    public virtual pcCode pcCode { get; set; } 
    //IVersionTracking
    public DateTime DateCreated { get; set; }
    public DateTime LastUpdated { get; set; }
    [Timestamp]
    public byte[] Version { get; set; }
}
public class pcJobSchedule : IVersionTracking, IpcIdentity
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public long Id { get; set; }
    //IpcIdentity
    [Required]
    [MaxLength(75)] 
    public string name { get; set; }
    [MaxLength(1000)] 
    public string description { get; set; }
    //FK to the JobAction table
    public long pcJobActionId { get; set; }
    public virtual pcJobAction pcJobAction { get; set; }
    //FK to the codes table (to indetify the schedule type: daily, weekly, etc)
    public long pcCodeId { get; set; }
    public virtual pcCode pcCode { get; set; } 
    public DateTime StartDate { get; set; }
    public Boolean dayMonday { get; set; }
    public Boolean dayTuesday { get; set; }
    public Boolean dayWednesday { get; set; }
    public Boolean dayThursday { get; set; }
    public Boolean dayFriday { get; set; }
    public Boolean daySaturday { get; set; }
    public Boolean daySunday { get; set; }
    public Boolean ThisJobIsNext { get; set; }
    public DateTime EndDate { get; set; }
    public int DateOfMonth { get; set; }
    public int DayOfWeek { get; set; }
    public DateTime ScheduleHour { get; set; }
    public int EveryHowMany { get; set; }
    public DateTime RunTimeLast { get; set; }
    public DateTime RunTimeNext { get; set; }
    //IVersionTracking
    public DateTime DateCreated { get; set; }
    public DateTime LastUpdated { get; set; }
    [Timestamp]
    public byte[] Version { get; set; }
}

如何构建实体框架应用程序(使用 MEF)

从您的架构描述中,我可以假设您的主机应用程序在某处有一个 [ImportMany] 导致您的所有插件都由 MEF 实例化吗?

如果是这种情况,一种选择是(我相信您问过)将事件添加到插件接口,并从主机应用程序附加到每个插件中的该事件。 我自己也这样做了,效果很好。

如果 EF 类

适合您的体系结构,另一种选择是将 EF 类放在单独的程序集中,在插件程序集中引用该程序集,并直接从插件执行数据访问。

我自己完成了第二个选项,其中我将 EF 代码优先类放入单独的程序集中,并有一些用于连接到上下文类和查询 ef 存储库的帮助程序类。但是,如果您不希望插件直接访问整个数据库,那么最好选择选项 1。特别是如果将来您决定将数据库表拆分为不同的模式,并且仅希望某些插件仅与数据库中的特定模式进行交互。