【问题标题】:ASP.NET EntityFramework 4 data context issuesASP.NET EntityFramework 4 数据上下文问题
【发布时间】:2019-03-13 02:42:14
【问题描述】:

我正在开发一个网站,解决方案中有两个项目,一个是业务逻辑项目,一个是网站项目。我知道我想将实体上下文排除在 Web 项目之外,并且只使用框架创建的业务对象,但我不知道如何以这种方式保存修改后的对象。

假设我的实体模型创建了这个类:

public class Person //Person entity
{
    Int32 Id {get;set;}
    String Name {get;set;}
    Address Address {get;set;} //Address entity
}

我创建了这个类来获取特定的人:

public static class PersonController
{
    public static Person GetById(int id)
    {
        using (Entities context = new Entities())
        {
            return context.Persons.FirstOrDefault(x => x.Id == id);
        }
    }
}

这允许我通过调用 PersonController.GetById(1); 来获取没有上下文的人;并且我可以在获取人员属性后更改它们,但我不知道如何将修改后的信息保存回数据库。理想情况下,我想部分类 Person 并添加一个 .Save() 方法,该方法将处理创建一个上下文,将人员添加到其中并保存更改。但是当我前一阵子尝试这个时,它仍然附加到旧上下文中存在各种问题,即使我将它分离并将其附加到新上下文,如果我没记错的话,它也会附加为 EntityState.Unchanged,所以当我在附加后调用 context.SaveChages() 时,实际上没有任何更新。

我想我有两个问题:

1) 我是否以一种好的方式来解决这个问题/是否有更好的方式?如果我以一种非常糟糕的方式这样做,我将不胜感激一些伪代码来为我指明正确的方向;一个指向解释如何处理这类事情的帖子的链接也可以。

2) 有人可以为保存方法提供一些伪代码吗?如果附加或删除地址,save 方法也需要处理。

【问题讨论】:

    标签: asp.net entity-framework-4


    【解决方案1】:

    有很多方法可以将实体框架作为持久层来处理。

    首先,您似乎没有使用纯 POCO。也就是说,您让 EF 为您(在 EDMX.designer.cs 文件中)生成类。

    这并没有错,但它确实阻碍了关注点的清晰分离(尤其是在单元测试方面)。

    您是否考虑实施存储库模式来封装您的 EF 逻辑?这是将逻辑与 UI 隔离的好方法。

    在保存方面 - 这是困难的地方。你是对的,大多数人使用部分类。通常,您将有一个基类,它公开一个虚拟的“保存”方法,然后部分类可以覆盖该方法。

    我个人不喜欢这种模式——我认为 POCO 不应该关心持久性或底层基础设施。因此,我喜欢使用纯 POCO(无代码生成)、存储库模式和工作单元。

    工作单元为您处理上下文打开/保存/关闭。

    这就是(我的)工作单元如何发挥作用。考虑一下您的“Web”项目中的一些代码:

    var uOw = new UnitOfWork(); // this is class i created, implementing the UOW pattern
    var person = repository.Find(10); // find's a "Person" entity (pure POCO), with id 10.
    person.Name = "Scott";
    uOw.Commit();
    

    或者添加一个新的人:

    var uOw = new UnitOfWork();
    var newPerson = new Person { Name = "Bob" };
    repository.Add(newPerson);
    uOw.Commit();
    

    这有多好? :)

    第 1 行为您创建了一个新的 sql 上下文。
    第 2 行使用相同的上下文来检索单个“Person”对象,该对象是手动编码的 POCO(不是由 EF 生成的)。
    第 3 行更改了 Person 的名称(纯 POCO 设置器)。
    第 4 行保存对数据上下文的更改,并关闭上下文。

    现在,这些模式远不止这些,所以我建议你阅读这些模式,看看它是否适合你。

    我的存储库也是使用泛型实现的,因此我可以将这个接口重用于所有业务实体的持久性。

    还可以看看我在 Stack Overflow 上提出的其他一些问题 - 你可以看到我是如何实现这些模式的。

    不确定这是否是您正在寻找的“答案”,但我想我会给您一些替代选择。

    【讨论】:

    • 我是一个相当新的开发人员,所以我对设计模式还没有很多经验。因此,我真的不知道如何使用存储库模式,但我可以查一下。为什么你不想使用 EF 生成的对象呢?我认为 EF 的全部意义在于它会自动生成对象,这应该可以节省您的编码时间;既是因为您不必编写太多代码,又因为您无需测试您未编写的代码。
    • 好吧,原因太多了,这里就不一一赘述了。主要的一个是可扩展性。如果您让 EF 生成您的类,这些类将“绑定”到 EF,并且是数据库感知的。他们需要知道他们是如何被使用的(映射)。对于 POCO,他们不知道。因此,您可以为 nHibernate 切换 EF(例如)而无需额外的代码更改。此外,您的类现在纯粹代表您的域模型 - 它们不会被导航属性和事件委托所困扰。不过,对于简单的应用程序(不会长期存在的应用程序),EF gen 很好。
    • RE 测试 - 您不直接测试类,但例如,如果您有一个服务层(大多数应用程序都有),您需要确保您可以创建/检索/删除实体。通过使用代码生成,您需要在测试服务层时引用实体框架。这不应该是必需的。你最终得到的是所有引用实体框架的项目——因此你放弃了“松散耦合”。
    • 好的,所以我想尝试实施像您这样的设置,但我是新手,我对存储库模式一无所知。如果我有一个例子,我会很快上手。有没有可以让我入门的教程?
    • 当然,伙计,这是我用来解决问题的(出色的)文章:huyrua.wordpress.com/2010/07/13/…。它涵盖了带有 POCO 的 EF、存储库和规范模式,所有这些都在 .NET 中。希望对您有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多