在 ascx 用户控件中将 UI 与数据访问分离

发布于 2024-08-15 09:15:10 字数 91 浏览 1 评论 0原文

设计 ascx 用户控件时将 UI 与数据访问分离的“最佳实践”是什么?我的用户控件是否应该像在我的项目中那样使用 3 层架构,或者我可以从用户控件内部进行数据访问吗?

What is the "best practice" for designing ascx user controls regarding separating the UI from the Data Access? Should my user control use 3 tier archetecture as in my projects or can I do the data acess from within the user control?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

两相知 2024-08-22 09:15:10

您永远不应该从用户控件访问数据库。您应该创建一个用于访问数据库的类,并且应用程序中的所有内容都应该使用该类。基本上,类中的方法将是存储过程调用的包装器,但应用程序(以及用户控件)看到的只是带有所需参数的方法。从应用程序的角度来看,不了解数据库。这允许您在不更改应用程序的情况下更改数据库。

此链接可能对您有帮助:

http://www.simple-talk.com/dotnet/.net-framework/.net-application-architecture-the-data-access-layer/

You should never access the database from a user control. You should create a class for accessing the database, and everything within your application should use that class. Basically, the methods in the class would be wrappers around your stored procedure calls, but all that the application (and therefore user controls) sees is a method with the needed parameters. No knowledge of the database from the application's point of view. That allows you to make changes to the database without changing your application.

This link might help you:

http://www.simple-talk.com/dotnet/.net-framework/.net-application-architecture-the-data-access-layer/

何必那么矫情 2024-08-22 09:15:10

现在无论一个项目多么简单或复杂,至少都应该分为表示层、业务层和数据层。在任何给定时间,这三者中的任何一个都可以改变而不影响其他人。

用户控件是表示层的一部分,它应该向业务层提供数据和用户操作,而业务层又解释数据和这些操作以做出决策。如果需要,业务层将调用数据层。数据层反过来将处理与数据库/源文件的所有通信。

将三者分开并保持分开并不是那么困难。

Now matter how simple or complex a project, at the very least, all should be separated into a Presentation Layer, Business Layer, and Data Layer. At any given time any one of the three could change without affecting the others.

A user control is part of the presentation layer, it should supply data and user actions to the business layer which in turn interprets the data and those actions to make decisions. If necessary the business layer would call the Data Layer. The Data Layer in turn would handle all communication with the database/source files.

It's not that hard to separate the three and keep them separate.

小姐丶请自重 2024-08-22 09:15:10

我肯定会建议从某种业务层访问数据。 UI 永远不应该直接访问数据库。

  • 如果您的访问规则发生变化怎么办?
  • 如果您的存储发生变化怎么办?
  • 您能否确保每个 UI 控件都能够执行业务规则?
  • ETC。

I would definitely suggest to access data from some kind of business layer. UI never should access databases directly.

  • What if your access rules changed?
  • What if your storage changed?
  • Can you ensure, that every UI control is able to enforce business rules?
  • etc.
不再让梦枯萎 2024-08-22 09:15:10

这就是我的项目中的内容。

1.) Application.Infrastruct

  • 所有业务对象的基类、业务对象集合、数据访问类以及我的自定义属性和实用程序作为扩展方法、通用验证框架。这决定了我的最终 .net 应用程序的整体行为组织。

2.) Application.DataModel

  • 数据库的类型化数据集。
  • TableAdapters 扩展为包含事务和我可能需要的其他功能。

3.) Application.DataAccess

  • 数据访问类。
  • 使用底层类型数据集查询数据库操作的实际位置。

4.) Application.DomainObjects

  • 业务对象和业务对象集合。
  • 枚举。

5.) Application.BusinessLayer

  • 提供可从表示层访问的管理器类。
  • HttpHandlers。
  • 我自己的 Page 基类。
  • 更多内容请参见此处。

6.) Application.WebClientApplication.WindowsClient

  • 我的表示层
  • 从 Application.BusinessLayer 和 Application.BusinessObjects 获取引用。

Application.BusinessObjects 在整个应用程序中使用,并且只要需要,它们就会跨所有层 [Application.DataModel 和 Application.Infrastruct 除外]

我的所有查询都只定义了 Application.DataModel。

Application.DataAccess 返回或采用业务对象作为任何数据访问操作的一部分。业务对象是在反射属性的帮助下创建的。每个业务对象都标记有映射到数据库中的目标表的属性,并且业务对象内的属性标记有映射到相应数据库表中的目标列的属性。

我的验证框架允许我在指定的 ValidationAttribute 的帮助下验证每个字段。

我的框架大量使用属性来自动执行大多数繁琐的任务,例如映射和验证。我还可以将新功能作为框架中的新方面。

在我的应用程序中,示例业务对象如下所示。

User.cs

[TableMapping("Users")]
public class User : EntityBase
{
    #region Constructor(s)
    public AppUser()
    {
        BookCollection = new BookCollection();
    }
    #endregion

    #region Properties

    #region Default Properties - Direct Field Mapping using DataFieldMappingAttribute

    private System.Int32 _UserId;

    private System.String _FirstName;
    private System.String _LastName;
    private System.String _UserName;
    private System.Boolean _IsActive;

    [DataFieldMapping("UserID")]
    [DataObjectFieldAttribute(true, true, false)]
    [NotNullOrEmpty(Message = "UserID From Users Table Is Required.")]
    public override int Id
    {
        get
        {
            return _UserId;
        }
        set
        {
            _UserId = value;
        }
    }

    [DataFieldMapping("UserName")]
    [Searchable]
    [NotNullOrEmpty(Message = "Username Is Required.")]
    public string UserName
    {
        get
        {
            return _UserName;
        }
        set
        {
            _UserName = value;
        }
    }

    [DataFieldMapping("FirstName")]
    [Searchable]
    public string FirstName
    {
        get
        {
            return _FirstName;
        }
        set
        {
            _FirstName = value;
        }
    }

    [DataFieldMapping("LastName")]
    [Searchable]
    public string LastName
    {
        get
        {
            return _LastName;
        }
        set
        {
            _LastName = value;
        }
    }

    [DataFieldMapping("IsActive")]
    public bool IsActive
    {
        get
        {
            return _IsActive;
        }
        set
        {
            _IsActive = value;
        }
    }

    #region One-To-Many Mappings
    public BookCollection Books { get; set; }

    #endregion

    #region Derived Properties
    public string FullName { get { return this.FirstName + " " + this.LastName; } }

    #endregion

    #endregion

    public override bool Validate()
    {
        bool baseValid = base.Validate();
        bool localValid = Books.Validate();
        return baseValid && localValid;
    }
}

BookCollection.cs

/// <summary>
/// The BookCollection class is designed to work with lists of instances of Book.
/// </summary>
public class BookCollection : EntityCollectionBase<Book>
{
    /// <summary>
    /// Initializes a new instance of the BookCollection class.
    /// </summary>
    public BookCollection()
    {
    }

    /// <summary>
    /// Initializes a new instance of the BookCollection class.
    /// </summary>
    public BookCollection (IList<Book> initialList)
        : base(initialList)
    {
    }
}

This is what I have in my project.

1.) Application.Infrastructure

  • Base classes for all businessobjects, busines object collection, data-access classes and my custom attributes and utilities as extension methods, Generic validation framework. This determines overall behavior organization of my final .net application.

2.) Application.DataModel

  • Typed Dataset for the Database.
  • TableAdapters extended to incorporate Transactions and other features I may need.

3.) Application.DataAccess

  • Data access classes.
  • Actual place where Database actions are queried using underlying Typed Dataset.

4.) Application.DomainObjects

  • Business objects and Business object collections.
  • Enums.

5.) Application.BusinessLayer

  • Provides manager classes accessible from Presentation layer.
  • HttpHandlers.
  • My own Page base class.
  • More things go here..

6.) Application.WebClient or Application.WindowsClient

  • My presentation layer
  • Takes references from Application.BusinessLayer and Application.BusinessObjects.

Application.BusinessObjects are used across the application and they travel across all layers whenever neeeded [except Application.DataModel and Application.Infrastructure]

All my queries are defined only Application.DataModel.

Application.DataAccess returns or takes Business objects as part of any data-access operation. Business objects are created with the help of reflection attributes. Each business object is marked with an attribute mapping to target table in database and properties within the business object are marked with attributes mapping to target coloumn in respective data-base table.

My validation framework lets me validate each field with the help of designated ValidationAttribute.

My framrwork heavily uses Attributes to automate most of the tedious tasks like mapping and validation. I can also new feature as new aspect in the framework.

A sample business object would look like this in my application.

User.cs

[TableMapping("Users")]
public class User : EntityBase
{
    #region Constructor(s)
    public AppUser()
    {
        BookCollection = new BookCollection();
    }
    #endregion

    #region Properties

    #region Default Properties - Direct Field Mapping using DataFieldMappingAttribute

    private System.Int32 _UserId;

    private System.String _FirstName;
    private System.String _LastName;
    private System.String _UserName;
    private System.Boolean _IsActive;

    [DataFieldMapping("UserID")]
    [DataObjectFieldAttribute(true, true, false)]
    [NotNullOrEmpty(Message = "UserID From Users Table Is Required.")]
    public override int Id
    {
        get
        {
            return _UserId;
        }
        set
        {
            _UserId = value;
        }
    }

    [DataFieldMapping("UserName")]
    [Searchable]
    [NotNullOrEmpty(Message = "Username Is Required.")]
    public string UserName
    {
        get
        {
            return _UserName;
        }
        set
        {
            _UserName = value;
        }
    }

    [DataFieldMapping("FirstName")]
    [Searchable]
    public string FirstName
    {
        get
        {
            return _FirstName;
        }
        set
        {
            _FirstName = value;
        }
    }

    [DataFieldMapping("LastName")]
    [Searchable]
    public string LastName
    {
        get
        {
            return _LastName;
        }
        set
        {
            _LastName = value;
        }
    }

    [DataFieldMapping("IsActive")]
    public bool IsActive
    {
        get
        {
            return _IsActive;
        }
        set
        {
            _IsActive = value;
        }
    }

    #region One-To-Many Mappings
    public BookCollection Books { get; set; }

    #endregion

    #region Derived Properties
    public string FullName { get { return this.FirstName + " " + this.LastName; } }

    #endregion

    #endregion

    public override bool Validate()
    {
        bool baseValid = base.Validate();
        bool localValid = Books.Validate();
        return baseValid && localValid;
    }
}

BookCollection.cs

/// <summary>
/// The BookCollection class is designed to work with lists of instances of Book.
/// </summary>
public class BookCollection : EntityCollectionBase<Book>
{
    /// <summary>
    /// Initializes a new instance of the BookCollection class.
    /// </summary>
    public BookCollection()
    {
    }

    /// <summary>
    /// Initializes a new instance of the BookCollection class.
    /// </summary>
    public BookCollection (IList<Book> initialList)
        : base(initialList)
    {
    }
}
墨落画卷 2024-08-22 09:15:10

您至少需要一个 2 层解决方案:数据,然后是其他所有内容。对于更复杂的项目,您需要将其他所有内容抽象为表示、逻辑和数据。数据还可以分为数据访问层和数据模型层。

You need at a minimum, a 2 layer solution: data, then everything else. For a more complex project, you need to take that everything else and abstract it out into presentation, logic, data. Data can also be separated into data access and data model layers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文