【问题标题】:Linq to Sql and separation of concerns - am I doing this right?Linq to Sql 和关注点分离 - 我这样做对吗?
【发布时间】:2013-12-06 23:50:06
【问题描述】:

我有一个正在使用 LINQ to SQL 的项目,并且我已经设置了要在我的 Web 应用程序中使用的业务对象/模型。我正在寻找一些关于我如何设置这一切的反馈,看看它是否有意义,以及是否有什么我应该做的不同的事情。

这是一个示例模型:

public class User
{
    private MyDataContext _db = new MyDataContext();
    private MyLINQUserClass _user = new MyLINQUserClass();

    public string Name
    {
        get
        {
             return _user.Name;
        }
        set
        {
             _user.Name = value;
        }
    }

    public User(int UserID)
    {
        _user = _db.Where(u => u.UserID == UserID).FirstOrDefault();
        if (_user == null)
        {
            _user = new MyLINQUserClass();
        }
    }

    internal User(MyLINQUserClass user, MyDataContext db)
    {
        _db = db;
        _user = user;
    }

    public void Save()
    {
        _db.SubmitChanges();
    }

    public static User Add(string Name)
    {
        MyDataContext _db = new MyDataContext();
        MyLINQUserClass _user = new MyLINQUserClass();

        _user.Name = Name;
        _db.MyLINQUserTable.InsertOnSubmit(_user);
        _db.SubmitChanges();

        return new User(_user, _db);
    }

    public static IList<User> Get()
    {
        MyDataContext _db = new MyDataContext();
        return _db.MyLINQUserTable.Select(u => new User(u, _db)).ToList();
    }
}

为了清楚起见,我在项目中已经大量使用了这种类型的模型(上面只是我为发布的帖子而拼凑的一个示例)并且效果很好。我的问题更像是一个“学习”问题......我知道它有效。我只是不确定是否有一些我应该做的更好的不同的事情,如果是,为什么。

想法?

【问题讨论】:

  • 你做这些抽象只是为了实现一个 ActiveRecord 模式吗?
  • 老实说,我并没有真正遵循任何特定的模式。我只是想将我的表示层、业务对象和数据对象分开。
  • 我真的不喜欢像这样将实体与数据层混合。虽然它有效(如您所说),但您正在将数据逻辑发送到表示层。我宁愿有一个 poco 实体和一个单独的数据层,可能使用存储库模式。
  • 虽然我同意 Mattias 不要将存储库模式与实体框架之类的 ORM 一起使用,但这只是对作为数据层抽象的 ORM 的不必要抽象。

标签: c# linq-to-sql separation-of-concerns


【解决方案1】:

我想这类问题没有正确的答案。这是设计、偏好和要求的问题。我会尝试展示我的观点...

我一直很喜欢 Repository pattern 以将顾虑分开。我将使用 T 类型的存储库来检索 T 实体(谈论泛型)。这些将是参与我的商业模式的实体。在您的情况下,我将有一个 UsersRepository 类,返回 User 实体。此数据访问层 (DAL) 将处理我的数据访问问题

我的商业模式将使用实体来开展业务。在简单的 CRUD 应用程序中,可能不需要我的存储库返回的实体以外的其他对象。在更复杂的应用程序中,将需要新的类,使用 DAL 的存储库来检索作为实体的数据。这个业务层将处理我的主要业务功能问题(计算等)

然后,出于显示目的,您可能需要另一个结构。例如,如果您关注MVC pattern(您也可以看到Microsoft article),您将需要创建另一个模型来满足您的显示目的。这个遵循 MVC 模式的 GUI 层将处理我的图形显示问题

希望我能帮上忙!

【讨论】:

    【解决方案2】:

    这就是所谓的数据访问对象模式。 UserMyLINQUserClass 的 DAO,可以称为域类。

    DAO 模式是为单一职责而设计的:只有 DAO“了解”数据层,而领域类可以专注于业务逻辑。领域类是persistence ignorant。到目前为止,一切顺利。

    但是,这种模式有(至少)三个很大的缺点:

    • 它往往会创建大量样板代码
    • 很难组合对象图,因为 DAO 仅代表数据库中的一行,并且获取对象图很容易退化为每个对象或子对象集合的一个查询。
    • 很难以事务方式工作,因为 DAO 无法管理跨越整个对象图的事务。因此,您需要一些总体层来处理事务。

    然而,大多数 ORM 具有与 DAO 不同的持久性忽略模型。他们有存储库和工作单元。在 L2S 中,Table 是一个基本存储库,而上下文是一个工作单元。 “域”类,如MyLINQUserClass,可以被认为是持久性无知的。 (承认,它们充满了用于持久性和更改跟踪的样板代码,但它是生成的,实际上可以忽略)。因此,CRUD 操作的所有职责都已分配,无需其他对象承担这些职责。

    您实现它的方式使得处理对象图和事务变得更加困难,因为每个 DAO 都有自己的上下文,因此您不能以将 LINQ 转换为一个 SQL 语句的方式编写涉及多个 DAO 的 LINQ 查询.在一个事务中执行多个保存操作是一项挑战。

    结论

    通过在 linq-to-sql 环境中使用 DAO,您将混合 CRUD 职责。您得到了 DAO 模式的所有缺点,并且无法充分利用存储库/UoW 模式的强大功能。我强烈建议二选一,我会选择 L2S(好吧,实际上我会选择 Entity Framework)。

    【讨论】:

    • 我之所以按照我的方式进行设置,是因为我不希望我的表示层直接使用 L2S 类。基本上我想要实现的是表示层(在这种情况下,是一个 Web Forms ASP.net 应用程序)-> 业务对象(如上面的示例类)-> 数据访问层(L2S)。
    • 在表示层中有 L2S 类并不总是像人们说的那么糟糕,但通常您会创建 DTO 和/或视图模型以将域/DAL 与表示层分开。跨度>
    • 我实际上考虑过这些模型。实际上它们在解决方案中的 Models 项目中。
    猜你喜欢
    • 2010-09-08
    • 1970-01-01
    • 2012-08-13
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-13
    • 1970-01-01
    相关资源
    最近更新 更多