简化我的分组

发布于 2024-10-19 09:03:00 字数 1793 浏览 1 评论 0原文

您好,我想将组数据返回到 ui 层。

这是我想要通过“GenerationDate”简化分组并返回 List<> 中的数据的方法回到 UI 网格视图。 我发现这很麻烦,因为我必须做forloop。另外,在 UI 层中,我必须为这个简单的 groupby 执行另一个 forloop。你能帮忙简化一下吗?

public List<SalaryTracker> GetSalaryTrackerOrderByGenerationDate(int tutorId)
{
    List<SalaryTracker> salary = new List<SalaryTracker>();
    using (leDataContext db = new leDataContext())
    {
        try
        {
            var r = 
                from s in db.SalaryTrackers
                where s.StaffId == 2 && s.PaymentDate == null
                group s by s.GenerationDate into g
                where g.Count() > 0
                select new
                {
                    date = g.Key, totalSalary = g.Sum(p => p.SalaryAmount)
                };

            foreach (var rr in r)
            {
                SalaryTracker m = new SalaryTracker();
                m.GenerationDate = rr.date;
                m.SalaryAmount = rr.totalSalary;
                salary.Add(m);
            }

            return salary; 
        }
        catch (Exception ex)
        {
            Logger.Error(typeof(SalaryTracker), ex.ToString());
            throw;
        }                    
    }
}

--------------- GUI

totalCommissionsGroup = salary.GetSalaryTrackerOrderByGenerationDate(tutor.Id);

IList<SalaryTracker> rr = (
    totalCommissionsGroup.GroupBy(x => x.GenerationDate)
    .Select(g => new SalaryTracker
    {
        MonthId = g.Key.Month,
        MonthToPay = common.GetMonthName(Convert.ToInt16(g.Key), true),
        SalaryAmount = g.Sum(x => x.SalaryAmount)
    })).ToList<SalaryTracker>();  

gvSalaryPayment.DataSource = rr;           

我这样做是为了获得字符串中的 MonthToPay

hi i would like to return the group data back to the ui layer.

here is how i want to do a simplify the groupby "GenerationDate" and return the data in List<> back to UI gridview.
i find it very troublesome as i got to do the forloop. Also in the UI layer i got to do another forloop for this simple groupby. Could you help to simplify it?

public List<SalaryTracker> GetSalaryTrackerOrderByGenerationDate(int tutorId)
{
    List<SalaryTracker> salary = new List<SalaryTracker>();
    using (leDataContext db = new leDataContext())
    {
        try
        {
            var r = 
                from s in db.SalaryTrackers
                where s.StaffId == 2 && s.PaymentDate == null
                group s by s.GenerationDate into g
                where g.Count() > 0
                select new
                {
                    date = g.Key, totalSalary = g.Sum(p => p.SalaryAmount)
                };

            foreach (var rr in r)
            {
                SalaryTracker m = new SalaryTracker();
                m.GenerationDate = rr.date;
                m.SalaryAmount = rr.totalSalary;
                salary.Add(m);
            }

            return salary; 
        }
        catch (Exception ex)
        {
            Logger.Error(typeof(SalaryTracker), ex.ToString());
            throw;
        }                    
    }
}

--------------- GUI

totalCommissionsGroup = salary.GetSalaryTrackerOrderByGenerationDate(tutor.Id);

IList<SalaryTracker> rr = (
    totalCommissionsGroup.GroupBy(x => x.GenerationDate)
    .Select(g => new SalaryTracker
    {
        MonthId = g.Key.Month,
        MonthToPay = common.GetMonthName(Convert.ToInt16(g.Key), true),
        SalaryAmount = g.Sum(x => x.SalaryAmount)
    })).ToList<SalaryTracker>();  

gvSalaryPayment.DataSource = rr;           

i do this so that i can get the MonthToPay in string

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

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

发布评论

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

评论(2

苏别ゝ 2024-10-26 09:03:00
public List<SalaryTracker> GetSalaryTrackerOrderByGenerationDate(int tutorId)
{
    using (var db = new leDataContext())
    {
        try
        {
            return (
                from s in db.SalaryTrackers
                where s.StaffId == 2 && s.PaymentDate == null
                group s by s.GenerationDate into g
                select new
                { 
                    MonthId = g.Key.Month,
                    // I don't know what "common" is in your UI code, 
                    // I am just using GetMonthName here
                    MonthToPay = GetMonthName(Convert.ToInt16(g.Key), true), 
                    SalaryAmount = g.Sum(p => p.SalaryAmount)  
                })
                .AsEnumerable()
                .Select(x => new SalaryTracker 
                { 
                    MonthId = x.MonthId,
                    MonthToPay = x.MonthToPay, 
                    SalaryAmount = x.SalaryAmount  
                })
                .ToList();
        }
        catch (Exception ex)
        {
            Logger.Error(typeof(SalaryTracker), ex.ToString());
            throw;
        }
    }
}
public List<SalaryTracker> GetSalaryTrackerOrderByGenerationDate(int tutorId)
{
    using (var db = new leDataContext())
    {
        try
        {
            return (
                from s in db.SalaryTrackers
                where s.StaffId == 2 && s.PaymentDate == null
                group s by s.GenerationDate into g
                select new
                { 
                    MonthId = g.Key.Month,
                    // I don't know what "common" is in your UI code, 
                    // I am just using GetMonthName here
                    MonthToPay = GetMonthName(Convert.ToInt16(g.Key), true), 
                    SalaryAmount = g.Sum(p => p.SalaryAmount)  
                })
                .AsEnumerable()
                .Select(x => new SalaryTracker 
                { 
                    MonthId = x.MonthId,
                    MonthToPay = x.MonthToPay, 
                    SalaryAmount = x.SalaryAmount  
                })
                .ToList();
        }
        catch (Exception ex)
        {
            Logger.Error(typeof(SalaryTracker), ex.ToString());
            throw;
        }
    }
}
山人契 2024-10-26 09:03:00

我同意 Mahesh Velaga 的重构(为此+1),并且我想补充一点,该应用程序级别的日志记录错误是不寻常的。特别是当您决定以任何方式重新抛出异常时。因此,我建议您删除带有错误日志记录的完整 try catch 并仅记录到应用程序的根目录中(如果您尚未这样做)。这使您的代码更加简洁。

当您完成此操作后,您会发现剩下的是一个很好的可读方法,除了业务逻辑之外几乎没有其他任何东西。

更新

但是如果我们不添加“try catch”
在数据模型层,如何
主要调用者捕获错误?我有
多年来一直使用这种模式..
如果我错了,请纠正我。参考
到此链接

了解您在问题中的做法或按照参考文章 您提供的几乎总是次优的,因为以下几个原因:

  • 在服务层捕获、记录和重新抛出是不幸的,因为您最终会在日志系统中得到此错误的双重条目,简单地说,因为您需要登录无论如何,您的应用程序的顶层,因为否则您将错过并非源自服务层的日志记录错误。忽略错误(通过重新抛出错误)也是一个坏主意,因为当错误发生时客户端几乎不应该继续。
  • 引用的文章中所示,在表示层捕获也是不幸的,因为这您不记录错误的方式,但更重要的是,您向用户提供了他们不理解的可能技术性和晦涩的错误消息(甚至可能是外语),这会让他们感到沮丧。更糟糕的是,它可能会导致信息泄露,使黑客能够在攻击您的应用程序时看到表面下发生的情况(如果是公开暴露的 Web 应用程序)。

这并不意味着您不能向用户显示任何错误信息,而只是对您显式抛出的异常执行此操作,以向用户显示错误信息。例如:

try
{
    // Call into service layer
}
catch (BusinessLayerException ex)
{
    this.ValidationSummary1.Add(new CustomValidator
    {
        ErrorMessage = ex.Message, IsValid = false
    });
}

在此示例中,BusinessLayerException 是从业务层引发的特殊异常,其中包含用户可以理解的错误消息(如果您的应用程序由以下用户使用,则可能包含本地化错误消息)多种语言的用户)。

对于所有其他异常,大多数时候您不想向用户显示确切的错误消息,因为您不知道出了什么问题、错误有多严重以及异常包含哪些信息。最好的办法是在表示层中尽可能减少错误处理逻辑,并在应用程序顶层的一个位置处理此问题。在这里,您确保在这种情况下向用户显示错误页面,并确保将错误记录到日志系统中。

您可以配置 ASP.NET 以显示发生错误时的自定义错误页面。下面是一个示例:

<customErrors mode="RemoteOnly" 
    defaultRedirect="~/ErrorPage.htm">
</customErrors>

ErrorPage.htm 可以显示一般信息,例如 Stackoverflow 上的一般“这是我们的错”错误页面。也许是支持人员的一些联系信息、您的家庭电话号码,以便他们可以在晚上给您打电话;-)

通过在 global.asax 中实现 Application_Error 方法,您可以在应用程序日志中的单个位置未处理的异常:

void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();

   // Log the exception here.
}

确保记录有关所需错误的所有信息,例如堆栈跟踪、错误消息、异常类型以及可能发生的所有内部异常。

我希望这有帮助。

I agree with the refactoring of Mahesh Velaga (+1 for that) and I like to add that logging errors at that level of the application is unusual. Especially when you decide to rethrow the exception any way. Therefore, I suggest that you remove the complete try catch with error logging and log only in the root of your application (if you're not already doing that). That makes your code much more cleaner.

When you've done that, you'll see that what's left is a nice readable method with hardly anything else than business logic.

UPDATE

But if we do not put the 'try catch'
in the datamodel layer, how would the
main caller catch the error? i have
been using this pattern for years..
please correct me if i am wrong. Refer
to this link.

Catching the way you do in your question or is done as is shown in the referenced article you provide is almost always sub optimal, because of several reasons:

  • Catching, logging and rethrowing at the service layer is unfortunate, because you will end up with double entries of this error in your logging system, simply, because you need to log at the top layer of your application anyway, because otherwise you will miss logging errors that do not originate from the service layer. Ignoring the error (by not rethrowing it) is also a bad idea, because the client should hardly ever continue when an error occurs.
  • Catching at the presentation layer as shown in the referenced article is also unfortunate, because this way you don't log the errors, but more importantly, you present the user with possibly technical and obscure error messages (perhaps even in a foreign language) that they don't understand and it will frustrate them. Even worse, it could lead to information leakage that allows hackers to see what going on under the surface when attacking your application (in case of a publicly exposed web application).

This doesn't mean that you can't display any error information to the users, but only do that for exceptions that you thrown explicitly to present error information for the users. For instance:

try
{
    // Call into service layer
}
catch (BusinessLayerException ex)
{
    this.ValidationSummary1.Add(new CustomValidator
    {
        ErrorMessage = ex.Message, IsValid = false
    });
}

In this example, the BusinessLayerException is a special exception that is thrown from the business layer that contains error messages that are understandable for the user (possibly with a localized error message if your application is used by users of multiple languages).

For all other exceptions, most of the time you don't want to show the user that exact error message, because you have no idea what went wrong and how severe the error is and what information the exception contains. The best thing to do is to have as less error handling logic as possible in your presentation layer, and handle this at one place in the top layer of the application. Here you ensure that an error page is displayed to the user in that case and you ensure that the error is logged to the logging system.

You can configure ASP.NET to show a custom error page in case of an error. Here's an example:

<customErrors mode="RemoteOnly" 
    defaultRedirect="~/ErrorPage.htm">
</customErrors>

The ErrorPage.htm can display general information like the general "it's our fault" error page here at Stackoverflow. Perhaps some contact information of support, your home phone number, so they can call you at night ;-)

By implementing the Application_Error method in the global.asax, you can at a single place in the application log unhandled exceptions:

void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();

   // Log the exception here.
}

Make sure you log al the information about the error you need, such as stack trace, error message, exception type, and all the inner exceptions that can occur.

I hope this helps.

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