【问题标题】:Implement a Save method for my object为我的对象实现 Save 方法
【发布时间】:2011-09-01 22:18:35
【问题描述】:

我正在尝试改进我的应用程序的设计,而不是从表示层调用 DataAccess 层。我将尝试在 BusinessObjects 层中实现我的对象的保存方法。但我不确定如何通过图层传递对象或其属性。例如,在我的旧设计中,我只是在表示层中创建对象的一个​​实例并为其分配属性,然后调用 DataAccess 方法将此信息保存在数据库中并将对象作为参数传递,如图所示。

DAL

public static void SaveObject(Object obj)
{
   int id = obj.id;
   string label = obj.label;
}

PL

Object obj = new Object();
obj.id = 1;
obj.label = "test";
DAL.SaveObject(obj); 

但我只想在我的 PL

中执行此操作
Object obj = new Object();
obj.id = 1;
obj.label = "test";
obj.SaveObject();

这可能吗?我的 DAL 会是什么样子?

编辑: 解释我的要求

我现在将我的代码基于我系统中一个非常重要的对象。

BusinessEntitiesLayer使用业务逻辑层

namespace BO.Cruises
{
    public class Cruise
    {
        public int ID
        { get; set; }

        public string Name
        { get; set; }

        public int BrandID
        { get; set; }

        public int ClassID
        { get; set; }

        public int CountryID
        { get; set; }

        public string ProfilePic
        { get; set; }

        public bool Hide
        { get; set; }

        public string Description
        { get; set; }

        public int OfficialRate
        { get; set; }

        public string DeckPlanPic
        { get; set; }

        public string CabinsLayoutPic
        { get; set; }

        public List<Itinerary> Itineraries
        { get; set; }

        public List<StatisticFact> Statistics
        { get; set; }

        public List<CabinRoomType> RoomTypesQuantities
        { get; set; }

        public List<CabinFeature> CabinFeatures
        { get; set; }

        public List<CruiseAmenity> Amenities
        { get; set; }

        public List<CruiseService> Services
        { get; set; }

        public List<CruiseEntertainment> Entertainment
        { get; set; }

        public List<CustomerReview> CustomerReviews
        { get; set; }
    }

}

BusinessLogicLayer 使用 DataAccessLayer

实际上这个层是用来验证我的对象然后调用 DAL 方法,但我现在没有实现任何验证,所以我只是用它来调用 DAL 方法。

    public static void Save(object cruise)
    {
        CruisesDAL.Save(cruise);
    }

DataAccessLayer 试图引用 BussinessEntities 但它给了我循环依赖错误!

它应该接收对象并将其转换为 Cruise 实体

    public static void Save(object cruise)
    {
         Cruise c = cruise as Cruise;

         //access the object c properties and save them to the database
    }

我的项目中的代码示例:

public static List<Cruise> GetCruisesList()
{
    string commandText = "SELECT ID, Name + CASE Hide WHEN 1 Then ' (Hidden)' ELSE '' END AS Name FROM Cruises";
    List<Cruise> cruises = new List<Cruise>();
    Cruise cruise;

    using (SqlConnection connection = new SqlConnection(ConnectionString))
    {
        using (SqlCommand command = new SqlCommand(commandText, connection))
        {
            connection.Open();

            using (SqlDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    cruise = new Cruise();

                    cruise.ID = Convert.ToInt32(reader["ID"]);
                    cruise.Name = reader["Name"].ToString();

                    cruises.Add(cruise);
                }
            }
        }
    }

    return cruises;
}

PresentationLayer 使用 BusinessEntities

输入控件(文本框、下拉列表等)

当点击保存按钮时,我获取所有值,创建一个 Cruise 对象并调用 Cruise.Save();

【问题讨论】:

标签: c# asp.net n-tier-architecture


【解决方案1】:

您应该避免将域模型与持久性逻辑混为一谈。 上面给出的示例将构成一个紧密耦合的解决方案。 为了实现 .SaveObject() 您可以在 BL 中创建可以完成这项工作的扩展方法。

BL.*

public static class ObjectPersistanceExtensions{

       public static SaveObejct<T>(this IBaseEntity obj){

            IObjectDal<T> _dal = AvailableSerices.Obtain<IObjectDal<T>>();
            _dal.AddObject(obj);
            _dal.Commit();
       }
}

因此,通过这种方式,您仍然可以将函数添加到域对象中,而无需耦合域对象中的逻辑。

【讨论】:

  • 很抱歉花了我这么长时间。但是如果你不介意的话,你会简化你的例子吗?
【解决方案2】:

将对象本身传递给数据层通常有点古怪。相反,我建议您让对象与数据层对话,让数据层做自己的事情。

internal static class DataLayer {

    public static bool Update(int id, string label) {
        // Update your data tier
        return success; // bool whether it succeeded or not
    }
}

internal class BusinessObject {

    public int ID {
        get;
        private set;
    } 

    public string Label {
        get;
        set;
    } 

    public bool Save() {
        return DataLayer.Update(this.ID, this.Label); // return data layer success
    }
}

您这样做的原因是因为您的数据层可能没有对您的业务对象的引用,因此不知道它是什么。您将无法传递对象本身。这是一个常见的场景,因为通常是您的业务对象程序集引用了您的数据层程序集。

如果您将所有内容都放在同一个程序集中,则上述内容不适用。但是,稍后,如果您决定将数据层重构为自己的模块(结果通常是这样,并且是好的设计),传递对象将会中断,因为它会丢失对您的业务对象的引用。

无论采用哪种方式,您都应该知道,如果添加新字段或成员,则必须同时更新对象和数据层。当您添加新内容时,这只是给定的。

我可能会为此写一篇关于一些好的设计实践的博客,但这是我的建议。

【讨论】:

  • 我知道你要去哪里,但我不喜欢在方法签名中列出所有成员的想法,我们应该传递类并封装属性,如果你有 25 个成员怎么办!?另外,你的 DAL 不是通用的,如果两个对象有一个 int 和一个字符串怎么办?
  • 这篇文章会很棒! :) 严重地。我需要学习好的设计,但这一切都在复杂而庞大的书中! ..关于我的层,我的解决方案中有 4 层,每一层都在一个单独的组件中。我不确定我是否理解你关于传递对象的事情。但我需要我的 DAL 才能使用 BusinessEntites 程序集,并且我不会将属性作为参数发送,因为它们很多!如果我对我的对象进行了任何更改,我将需要进行很多编辑。也许这就是你想说的,有时我会迷失在答案中,对此感到抱歉
  • @Davide Piras,如果一个对象有 25 个成员,那么您可能不会这样设计它。设计往往是根据需求来做的,他帖子里的需求也很基础,也很模糊。您可以选择许多设计模式来架构和实现,但这一切都回到了需求。在 IKashef,我将在今天晚些时候写一篇。我的网址在我的个人资料中
  • 我想现在我们都同意我不在方法参数中单独传递对象参数
  • 是的。当我完成这些网络表单的润色后,我会看一看并做出回应。
【解决方案3】:

如果您遵循此模式,您将在对象定义本身内部拥有保存逻辑,因此当您从 PL 调用时:

obj.SaveObject();

这将发生在对象本身:

public void SaveObject()
{
  DAL.SaveObject(this);
}

并且您的 DAL 与上面显示的相同。

这是设计问题,我不会将保存的逻辑放在对象中,但我会使用 BusinessManager 或 ObjectMapper 从 DAL 读取并保存到 DAL。

一般来说,在同一个位置(BusinessObject 或 BusinessManager)读取或加载和保存是一个很好的做法,但可以放在一起,这样您就可以轻松找到它们并在添加或更改字段时轻松更新它们。

【讨论】:

  • 嗯,实际上我有 BusinessLogic 层.. Object.Save() 调用 ObjectBLL.Save() 并验证数据然后将其发送到 DAL.Save(object obj)。这当然是我想要实现的,但它给了我一个循环依赖错误,当然在 DataAccess 层中使用我的实体层是必不可少的。无论如何我对设计不是很好,所以可以发布一些示例来说明您将如何以及在何处实现 Save 方法以及您会选择哪些层?
  • n 层方法的主要规则之一是不要从所有内容中引用所有内容。 PL 仅引用 BL 和 BL(业务逻辑)引用 DAL,DAL 对 PL 不可用,没有循环引用。然后,实体在称为 Core 或 Common 的单独类库中定义,并被所有层引用。我们还为实体和接口使用分离的类库,PL 只引用接口,BL 两者都引用,创建实体并将接口返回给 PL。相当扎实!
  • 我明白,但我现在有 4 层,每层都在一个单独的项目中。 PL、BO、BL、DAL .. 我知道如何引用 3 层,但现在呢?你认为在 Objects 层实现一个 save 方法是件好事吗?我只是认为最好将保存方法设为非静态而不是直接调用 BLL 或 DAL 方法
  • 我很好奇 PL 为什么不引用 BusinessObjects .. 我认为这非常重要,因此我可以将我的对象发送给 DAL,然后它将能够查看对象属性并将它们添加到我的 SqlCommand 作为参数然后执行它.. 我错过了什么吗?
  • PL 知道属性,因为知道对象实现的接口。 BL 知道一切并实例化实体但返回接口,DAL 可以只知道接口。正如大卫安德森所说,最后是关于需求。您的项目中有多少个不同的实体,项目有多大...
猜你喜欢
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
相关资源
最近更新 更多