Part of the web application I'm working on is an area displaying messages from management to 1...n users. I have a DataAccess project that contains the LINQ to SQL classes, and a website project that is the UI. My database looks like this:
User -> MessageDetail <- Message <- MessageCategory
MessageDetail is a join table that also contains an IsRead flag.
The list of messages is grouped by category. I have two nested ListView controls on the page -- One outputs the group name, while a second one nested inside that is bound to MessageDetails and outputs the messages themselves. In the code-behind for the page listing the messages I have the following code:
protected void MessageListDataSource_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
var db = new DataContext();
// parse the input strings from the web form
int categoryIDFilter;
DateTime dateFilter;
string catFilterString = MessagesCategoryFilter.SelectedValue;
string dateFilterString = MessagesDateFilter.SelectedValue;
// TryParse will return default values if parsing is unsuccessful (i.e. if "all" is selected"):
// DateTime.MinValue for dates, 0 for int
DateTime.TryParse(dateFilterString, out dateFilter);
Int32.TryParse(catFilterString, out categoryIDFilter);
bool showRead = MessagesReadFilter.Checked;
var messages =
from detail in db.MessageDetails
where detail.UserID == (int)Session["UserID"]
where detail.Message.IsPublished
where detail.Message.MessageCategoryID == categoryIDFilter || (categoryIDFilter == 0)
where dateFilter == detail.Message.PublishDate.Value.Date || (dateFilter == DateTime.MinValue)
// is unread, showRead filter is on, or message was marked read today
where detail.IsRead == false || showRead || detail.ReadDate.Value.Date == DateTime.Today
orderby detail.Message.PublishDate descending
group detail by detail.Message.MessageCategory into categories
orderby categories.Key.Name
select new
{
MessageCategory = categories.Key,
MessageDetails = categories.Select(d => d)
};
e.Result = messages;
}
This code works, but sticking a huge LINQ statement like this in the code-behind for a LinqDataSource control just doesn't sit right with me.
It seems like I'm still coding queries into the user interface, only now it's LINQ instead of SQL. However, I feel that building another layer between the L2S classes and the UI would cut back on some of the flexibility of LINQ. Isn't the whole point to reduce the amount of code you write to fetch data?
Is there some possible middle ground I'm not seeing, or am I just misunderstanding the way LINQ to SQL is supposed to be used? Advice would be greatly appreciated.