这个 4 层架构好吗?(异常处理对我来说很重要:)

发布于 2024-09-16 14:16:41 字数 2745 浏览 3 评论 0原文

我的应用程序中有以下层:

  • 实体
  • 数据库(带有实体引用)
  • 业务(带有数据库和实体引用)
  • 用户界面(带有业务和实体引用)

这是我的代码示例:

  • 数据库层中的 UserDAL 类:

public class UsersDal
{
    databaseDataContext db;
    public UsersDal()
    {
        try
        {
            db = new databaseDataContext(ConnectToDatabase.GetConnectionString());
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    public List<User> GetAllUsers()
    {
        try
        {
            return (from u in db.Users select u).ToList();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

等等...


在业务层中的 UserBLL 类中,我这样写:

public class UsersBll
{
    UsersDal user;
    public UsersBll()
    {
        try
        {
            user = new UsersDal();
        }
        catch(Exception ex)
        {
            throw new ProjectException(Errors.CannotCreateObject, ex);
        }
    }
    public List<User> GetAllUsers()
    {
        try
        {
            return user.GetAllUsers();
        }
        catch(Exception ex)
        {
            throw new ProjectException(Errors.CannotReadData, ex);
        }
    }

在 UI 中,我写:

    private void GetUsers()
    {
        try
        {
            UsersBll u = new UsersBll();
            datagrid.DataSource = u.GetAllUsers();
        }
        catch(ProjectException ex)
        {
            MessageBox(ex.UserMessage);// and also can show ex.InnerException.Message for more info
        }
    }

好吧,我使用一个 ProjectException 命名类来产生一个错误,其中包含我创建的 BLL 消息和操作系统自动操作的异常消息。 我还创建了一个可能错误的枚举和一个字典 以下是有关它的一些详细信息:

namespace Entities
{
    public enum Errors
    {
        CannotCreateObject,
        CannotReadData,
        CannotAdd,
        CannotEdit,
        CannotDelete,...
    }

[global::System.Serializable]
public class ProjectException : Exception
{
    public ProjectException(Errors er, Exception ex)
        : base(errors[er], ex)
    {
        currentEx = er;//er is Errors enum
    }
    static ProjectException()
    {
        errors = new Dictionary<Errors, string>();
        errors.Add(Errors.CannotCreateObject, "the application cannot connect to database!");
        errors.Add(Errors.CannotReadData, "the application cannot read data from database"); //...
    }
    public string UserMessage
    {
        get
        {
            try
            {
                return errors[currentEx];
            }
            catch
            {
                return "Unknown error!";
            }
        }
    }

这好吗? 它对我来说很好。 你有什么想法?

I have this layers in my application:

  • Entities
  • Database (with Entities reference)
  • Business (with database and Entities references)
  • User Interface (with Business and Entities references)

Here is an example of my codes:

  • UserDAL class in database layer:

public class UsersDal
{
    databaseDataContext db;
    public UsersDal()
    {
        try
        {
            db = new databaseDataContext(ConnectToDatabase.GetConnectionString());
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    public List<User> GetAllUsers()
    {
        try
        {
            return (from u in db.Users select u).ToList();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

And so on...


In the UserBLL class in Business layer i write like this:

public class UsersBll
{
    UsersDal user;
    public UsersBll()
    {
        try
        {
            user = new UsersDal();
        }
        catch(Exception ex)
        {
            throw new ProjectException(Errors.CannotCreateObject, ex);
        }
    }
    public List<User> GetAllUsers()
    {
        try
        {
            return user.GetAllUsers();
        }
        catch(Exception ex)
        {
            throw new ProjectException(Errors.CannotReadData, ex);
        }
    }

And in UI i write:

    private void GetUsers()
    {
        try
        {
            UsersBll u = new UsersBll();
            datagrid.DataSource = u.GetAllUsers();
        }
        catch(ProjectException ex)
        {
            MessageBox(ex.UserMessage);// and also can show ex.InnerException.Message for more info
        }
    }

Well, I use a ProjectException named class to produce an error contain a BLL created message by me and an Exception message that the OS automatically manipulate.
Also i create an enum of possible errors and a dictionary
here is some details about it:

namespace Entities
{
    public enum Errors
    {
        CannotCreateObject,
        CannotReadData,
        CannotAdd,
        CannotEdit,
        CannotDelete,...
    }

[global::System.Serializable]
public class ProjectException : Exception
{
    public ProjectException(Errors er, Exception ex)
        : base(errors[er], ex)
    {
        currentEx = er;//er is Errors enum
    }
    static ProjectException()
    {
        errors = new Dictionary<Errors, string>();
        errors.Add(Errors.CannotCreateObject, "the application cannot connect to database!");
        errors.Add(Errors.CannotReadData, "the application cannot read data from database"); //...
    }
    public string UserMessage
    {
        get
        {
            try
            {
                return errors[currentEx];
            }
            catch
            {
                return "Unknown error!";
            }
        }
    }

Is this good?
it work for me fine.
what's your idea?

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

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

发布评论

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

评论(1

笨死的猪 2024-09-23 14:16:41

catch (ex)中执行throw ex;几乎总是错误的。要么直接抛出;要么抛出新的whateverException("someMessage", ex);。决定使用前一种形式还是后者通常取决于您是否跨越应用程序层。如果从 DatabaseWrapper 类型派生的 AcmeServerDatabaseWrapper 在抛出 AcmeDatabaseTableNotFoundException 时正在执行查询,则它应该捕获该异常并将其作为 DatabaseWrapperTableNotFoundException(如果存在此类类型)或 DatabaseWrapperOperationFailedException 重新抛出。具有从 DatabaseWrapper 派生的对象的客户端代码应该能够知道该对象将抛出什么类型的异常,而不必知道它是什么类型的对象。任何从数据库层逃逸而没有被包装的异常都是客户端代码不太可能能够合理处理的异常,但可能会错误地处理(认为它发生在实际发生的上下文之外的上下文中)。

It is almost always wrong within a catch (ex) to do a throw ex;. Either just do throw; or else throw new whateverException("someMessage", ex);. The decision of whether to use the former form or the latter generally depends upon whether you are crossing an application layer. If an AcmeServerDatabaseWrapper, which derives from DatabaseWrapper type, is performing a query when an AcmeDatabaseTableNotFoundException is thrown, it should catch that and rethrow it as a DatabaseWrapperTableNotFoundException (if such a type exists) or as a DatabaseWrapperOperationFailedException. Client code which has an object derived from DatabaseWrapper should be able to know what types of exceptions that object will throw, without having to know what type of object it is. Any exception which escapes from the database layer without being wrapped is an exception the client code is unlikely to be able to handle sensibly, but might handle erroneously (thinking it occurred in a context other than where it actually happened).

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