【问题标题】:Building DAL. Using EDM (from database)构建 DAL。使用 EDM(来自数据库)
【发布时间】:2014-02-18 17:57:17
【问题描述】:

我必须开发一个在 windows (wpf) 中工作的 lob 应用程序,但应该以两种方式部署:

  • 使用本地数据库(同一台计算机)
  • 使用远程数据库(在同一网络中)

我将使用从数据库生成的实体数据模型(dbcontext,EF 4.0)(VS2012,sql server express 2012)

我想开发一个独特的数据访问层,UI 将绑定到该层,它将直接从 dbcontext(本地数据库)或从 dbcontext(远程数据库)公开数据的 WCF 服务获取数据

我不知道从哪里开始,我需要指导和示例,我知道这取决于应用程序的性质,但是一些示例、文章会很有帮助。我没有找到与我的需求相似的示例

我想我最好使用 DI 框架,但我想先关注 DAL。

【问题讨论】:

  • 您的问题中没有特定的 WPF 或 WPF 依赖...删除标签。
  • 好的,谢谢。我同意

标签: c# wcf entity-framework visual-studio-2012


【解决方案1】:

好吧,既然您想使用 DI 框架(可能是一个不错的选择 :)),您已经知道您需要使用接口来定义您的 DAL。然后,您可以拥有实现这些接口的类,这些接口充当 WCF 服务或 DB 上下文的适配器。

您设计的一个很好的方面是,您将自动将自己与 WCF 服务和数据库上下文的未来替代品隔离开来 - 即,每当 Microsoft 发布另一种数据访问技术时。 :) 或者更有可能的是,每当您的团队决定采用不同的团队时,例如从 WCF 服务切换到 REST 服务。

通常Repository pattern 用于解决此问题。例如,您可能有:

public interface IWidgetRepository
{
    // Query methods
    Widget GetById(string id);
    IEnumerable<Widget> GetAll();

    // Update methods
    void RenameWidget(string id, string newName);
    void UpdateWidgetPrice(string id, decimal newPrice);
}

但是,如果您尝试使存储库接口非常通用,那么当您开始意识到您想要拥有不同的查询功能等时,这很快就会变得令人生畏(例如,如果您尝试在 DAL 中实现 IQueryable,你还有很多工作要做!我试过了,但我放弃了,意识到我只是在浪费精力。)

最好的解决方法可能是使用预定义的查询方法,例如GetWidgetsWithOpenOrders()GetWidgetsWithFooBarComponents。然后在实现 IWidgetRepository 的适配器类中,您只需将这些查询映射到实体框架或 WCF 服务实现即可。

这样做的一个副作用是 DAL 将需要自己的一组数据传输对象 (DTO) - 因此您最终会在 DAL 命名空间中获得一个 Widget 类,并可能在 DB 中拥有其他 Widget 类上下文和/或 WCF 服务代理。您可以尝试通过强制 DB Context 对其数据库映射使用相同的 Widget 类来解决此问题,但我不建议这样做。 DB 上下文中的 DTO 用于适应数据库,WCF 服务中的 DTO 也是如此——它们是服务公开的数据协定。 DAL 中的 DTO 用于反映用户界面的需求(在 MVVM 术语中,它们是“模型”;在 OO 模式中,它们是针对不同数据访问策略的Façade)。

另一个副作用是创建 IWidgetRepository 的 stub/mock 实现非常容易,用于 1) 单元测试和 2) UI 的快速原型设计,而无需完全实现后端数据访问策略。

【讨论】:

  • 我想这些方法 ...GetWidgetsWithOpenOrders... 将使 DAL 中的数据保持最新,因为我想使用从 WPF 到 DAL 的绑定,它是自动的,但是从DAL 到另一边,我怎样才能保持数据的顺畅流动?如果我总是使用 WCF Servive,即使数据是本地的,你怎么看?,会不会有点慢?我可以使用 IIS Express。
  • 当然,如果您想依赖 WCF 服务作为您的 DAL 抽象,那么您可以一直使用它。如果您正确编码服务,它不会那么慢;除非您在您的服务上启用交易、可靠消息传递、安全性等,否则它将非常快速地执行。如果这是您能够维护的内部应用程序,那可能是最容易实现的。但那时你也真的不需要服务;只需使用远程数据库的连接字符串设置您的数据库上下文。然后 DB Context 成为你的 DAL 抽象。
  • 但是你放弃了灵活更换数据访问层、分离关注点等的想法。这是你必须做出的决定。我不建议走那条路,真的。但另一方面,为了“SOA”而“SOA”也没有真正的帮助,它只是意味着你需要做更多的工作。
  • 我认为您在存储库模式中遗漏了我所展示的存储库也将具有执行更新的方法。我会编辑答案来解释。
  • 感谢您的解释...另一方面,当您说“交换数据访问层”时,您的意思是与 Oracle 交换它?
【解决方案2】:

实现面向服务的架构,您的 UI 将根据用户或应用设置使用不同的服务,因此实例化访问本地 DB 或 WCF 服务的不同 DAL 对象...

-合同

namespace MyUIName.Services
{
    public interface IProductServiceAgent
    {
        List<Product> GetProducts();
    }
}

-代理

namespace MyUIName.Services
{
    public class ProductServiceAgent : BaseServiceAgent, IProductServiceAgent
    {
        //Contract implementation
        public List<Product> GetProducts()
        {
            if (Settings.Default.StoreType == "Local")
            {
                LocalStoreBIObject = new...
                LocalStoreBIObject.GetProducts();
            }
            if (Settings.Default.StoreType == "Remote")
            {
                RemoteStoreBIObject = new...
                RemoteStoreBIObject.GetProducts();
            }
        }
    }
}

-BI层

namespace BI
{
    public class LocalStoreBIObject
    {
        public List<Product> GetProducts()
        {
            //Do some BI stuff.
            //Instantiate appropriate DAL object
            return LocalStoreDALObjec.GetProducts(... pass in some BI params);
        }
    }
}

-DAL层

namespace DAL
{
    public class LocalStoreDALObject
    {
        public List<Product> GetProducts()
        {
            using (var localStoreContex = new...)
            {
                return localStoreContext.Products.Where(p => p... some logic);
            }
        }
    }
}

通过这种方式,您可以获得具有 BI 和 DAL 层的标准 3 层架构,允许您将业务逻辑保留在一层中,将数据访问逻辑和查询保留在单独的层中,并且您的服务代理决定使用哪些 BI 层对象取决于应用程序设置。另一个好处是,如果您需要该功能,这还允许您的用户在运行时切换数据存储...

显然,您不会在 DAL 层中的 BI 层中引用 Product 类,因此您必须创建一些中间对象或在 BI 中引用您的 EF 模型或使用元组来将数据从 DAL 传输到 BI 层或找到其他解决方案,但这只是您在此过程中必须解决的一个细节......

【讨论】:

  • 当两个用户同时请求dal方法时会发生什么。
  • 每次请求dal时给登录用户一个新的dal实例是否正确。
猜你喜欢
  • 2010-09-08
  • 1970-01-01
  • 2012-05-19
  • 1970-01-01
  • 2011-08-23
  • 1970-01-01
  • 1970-01-01
  • 2021-11-22
  • 1970-01-01
相关资源
最近更新 更多