【问题标题】:OOP: use Entity Framework only in the data access layerOOP:仅在数据访问层使用实体框架
【发布时间】:2017-07-31 06:03:59
【问题描述】:

我的应用程序有一个业务逻辑层和一个数据访问层。我只想让数据访问层访问数据库模型。现在,我可以轻松地做到这一点,但是我的 UI 类无法访问像 Reminder 这样的数据库类:

namespace Database
{
    using System;
    using System.Collections.Generic;

    public partial class Reminder
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public string Date { get; set; }
        public string RepeatType { get; set; }
        public string Note { get; set; }
        public long Enabled { get; set; }
        public string SoundFilePath { get; set; }
        public string PostponeDate { get; set; }
        public Nullable<long> EveryXCustom { get; set; }
        public string RepeatDays { get; set; }
        public Nullable<long> DayOfMonth { get; set; }
    }
}

在数据库类库里面

我使用这个提醒类来存储提醒。在我的 UI 类中,我出于各种原因使用这个类。

为了使用这个Reminder 类,我只需添加一个对需要使用它的类库的引用。这很好用,但问题是每个引用它的类库都可以像这样改变数据库。

如果我不使用实体框架,我可以简单地在模型之外有一个Reminder 类(因为没有模型)并将提醒从数据库加载到其中并在不使用实体框架的情况下提取它们。

这是一个示例,说明为什么我需要在我的 UI 类中使用 Reminder 类(这只是一个 UI 类的一小段代码示例)

此代码位于每 30 秒计时一次的计时器内

// We will check for reminders here every 30 seconds.
foreach (Reminder rem in BLReminder.GetReminders())
{
    // Create the popup. Do the other stuff afterwards.
    if(rem.PostponeDate != null && Convert.ToDateTime(rem.PostponeDate) <= DateTime.Now && rem.Enabled == 1)
    {
        allowRefreshListview = true;

        // temporarily disable it. When the user postpones the reminder, it will be re-enabled.
        rem.Enabled = 0;
        BLReminder.EditReminder(rem);

        MakePopup(rem);
    }
    else if(Convert.ToDateTime(rem.Date.Split(',')[0]) <= DateTime.Now && rem.PostponeDate == null && rem.Enabled == 1)
    {
        allowRefreshListview = true;

        // temporarily disable it. When the user postpones the reminder, it will be re-enabled.
        rem.Enabled = 0;
        BLReminder.EditReminder(rem);

        MakePopup(rem);
    }
}    

GetReminders 会从数据库中获取提醒并将它们放入提醒对象中

using (RemindMeDbEntities db = new RemindMeDbEntities())
{                
    localReminders = (from g in db.Reminder select g).ToList();
    db.Dispose();                
}

【问题讨论】:

    标签: c# winforms entity-framework sqlite oop


    【解决方案1】:

    您可以创建名为Shared 的单独项目,并将在许多项目中使用的所有类都放在那里。然后您需要通过 UI 项目和数据访问项目(以及使用这些类的其他人)引用该项目。

    两者都可以访问共享类,而 UI 将无法直接调用数据访问层。

    您也可以在数据访问层之外创建接口,但如果您的类是 DTO(数据传输对象),第一个选项会更好。

    【讨论】:

    • > 把许多项目中使用的所有类都放在那里。哪些课?模特的课?我认为这是不可能的
    • @stefan,你可以在另一个项目中拥有模型类,见nullablecode.com/2013/09/…和stackoverflow.com/questions/2464909/…
    • 我认为这是最好的解决方案,但现在我遇到了奇怪的错误。我按照您的链接进行指导,现在我的实体不知道这些类.. Visual Studio 的代码完成确实知道它。 @ 987654323@ 错误无法从 'Database.Entity.Reminder' 转换为 'Reminder' , Database.Entity 是具有分离模型类的类库来自实体的提醒仍在数据库(不是 Database.Entity)中RemindMeDbModel.Context.cs
    • 编辑:想通了。我不仅需要在 .Context.tt 上设置自定义工具,还必须从旧项目中删除 model.context.cs
    • 目前正在尝试修复新错误“无法加载指定的元数据资源”。 ...
    【解决方案2】:

    如果我不使用实体框架,我可以简单地提醒一下 模型外的类

    您可以在共享程序集中创建一个接口而不是模型外部的类:

    public interface IReminder
    {
        public long Id { get; }
        public string Name { get; }
        public string Date { get; }
        public string RepeatType { get; }
        public string Note { get; }
        public long Enabled { get; }
        public string SoundFilePath { get; }
        public string PostponeDate { get; }
        public Nullable<long> EveryXCustom { get; }
        public string RepeatDays { get; }
        public Nullable<long> DayOfMonth { get; }
    }
    

    您的实体可以实现接口:

    public partial class Reminder : IReminder
    {
        //...
    }
    

    也许您想让您的实体仅在内部可见并公开公共服务方法,例如IEnumerable&lt;IReminder&gt; GetReminders()

    【讨论】:

    • 嗯,我觉得这很有趣,所以我出去尝试了,但后来我遇到了问题。我无法创建接口的新实例,因此无法为其分配数据。我也不能再在业务逻辑层调用像 DLReminders.GetReminders() 这样的方法,因为这会给我这个错误i.imgur.com/bzCi4kq.png,这表明我试图避免的解决方案
    • @stefan 对于第一个问题,简单地创建一个派生自IReminder 的类并从中创建一个实例。对于第二个问题:不要将关注点分离与引用分离混淆;)如果您的业务层需要您的数据层,那么它也需要对它的引用。但是,我会选择只公开接口的 DataService,业务层使用该数据服务而不是原始实体。
    • 但是,不应该是业务逻辑层不能访问数据库吗?喜欢这张图片codeguru.com/images/article/19539/030318_01.gif
    猜你喜欢
    • 2011-11-14
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多