2011-03-27 62 views
0

我正在开发一个Web应用程序,该应用程序旨在根据用户选择的条件查询大型数据库表。在某些情况下,他们可能知道并输入主键,有时他们可能想查看过去7天内创建的状态'abc'的记录,或者其中描述包含'提案'这个词的'fred smith'创建的记录。要点是,根据他们的需求,他们可以很容易地指定10到20个不同的变量。ASP.NET 2.0 C#DAL多变量参数

我很容易建立sql语句并在网页后面的代码(aspx.cs)中动态应用参数。这种方法运作良好。然而,我一直在阅读关于使用BLL & DAL(甚至只是一个DAL),但我看到的所有例子都没有参数,例如getCategories()或单个参数,例如getProductByID( int productID)

所以我想建议的是如何最好的将许多参数的变量列表传递给BLL/DAL,而无需使用(例如)20个参数的方法(这是可行的,但看起来非常难以处理,特别是如果添加新的选择参数)。

我以为是

一)建立一个单一字符串参数可在方法进行解码,例如其他的想法:
字符串PARAMS =“的DateField =创建;没有fromdate = 2011-03- 01; Status = abc“
BLL.getRecords(params);
(可行的,但可怕和容易出错)

b)利用一个结构或一个类作为参数,例如
params.Status = “ABC”;
params.createdByUser = 23;

(是否有与有机会获得这个结构/类DAL的问题吗?我读过的DAL不应与调用它的类共享任何引用?

感谢您的任何建议如何你会实现这个场景。

回答

0

在我的项目,我创建静态类DataManager暴露所需的所有功能,获得数据,例如

public static IList<ActionHistoryData> GetActionHistoryList(DateTime startDate, DateTime endDate, bool postprocessed) 
{ 
    return GlobalComponents.DataManagerImpl.GetActionHistoryList(null, null, null, null, null, null, null, startDate, endDate, false, postprocessed, null); 
} 

public static ActionHistoryData GetActionHistory(int id) 
{ 
    IList<ActionHistoryData> actionHistoryList = 
     GlobalComponents.DataManagerImpl.GetActionHistoryList(id, null, null, null, null, null, null, null, null, null, null, null); 
    CQGUtils.Verify(!CollectionsUtil.IsEmpty(actionHistoryList), "There is no action history with [ID='{0}']", id); 
    CQGUtils.Verify(actionHistoryList.Count == 1, "More than one action history returned."); 
    return actionHistoryList[0]; 
} 

正如你在DB看到我们只有一个存储过程GetActionHistoryList(用于ActionHistory表数据),它有许多不同的参数。 存储过程包含动态SQL例如

`<select statement part>` 

DECLARE @where nvarchar(4000); 
SET @where = N' WHERE ' 
IF @ID IS NOT NULL 
    SET @where = @where + '(ah.ID = @ID) AND ' 
IF @AccountID IS NOT NULL 
    SET @where = @where + '(ah.AccountID = @AccountID) AND ' 
IF @SourceKind IS NOT NULL 
    SET @where = @where + '(ah.SourceKind = @SourceKind) AND ' 
IF @SourceIDArray IS NOT NULL 
    SET @where = @where + '(ah.SourceID IN ('+ @SourceIDArray +') 
IF @Postprocessed IS NOT NULL 
    SET @where = @where + '(ah.Postprocessed = @Postprocessed) AND ' 
IF @StartDate IS NOT NULL 
    SET @where = @where + '(ah.UtcTimestamp >= @StartDate) AND ' 
IF @EndDate IS NOT NULL 
    SET @where = @where + '(ah.UtcTimestamp <= @EndDate) AND ' 
) AND ' 

SET @where = @where + ' 1=1' 
SET @query = @[email protected]+' order by utcTimestamp desc ' 

EXEC sp_executesql @query, 
N' 
    @ID int, 
    @AccountID int, 
    @SourceKind tinyint, 
    @SourceIDArray nvarchar(max), 
    @NotificationID int, 
    @DataRequestID int, 
    @NotificationName nvarchar(250), 
    @StartDate datetime, 
    @EndDate datetime, 
    @MostRecent bit, 
    @Postprocessed bit, 
    @TopLimit int 
', 
@ID = @ID, 
@AccountID = @AccountID, 
@SourceKind = @SourceKind, 
@SourceIDArray = @SourceIDArray, 
@NotificationID = @NotificationID, 
@DataRequestID = @DataRequestID, 
@NotificationName = @NotificationName, 
@StartDate = @StartDate, 
@EndDate = @EndDate, 
@MostRecent = @MostRecent, 
@Postprocessed = @Postprocessed, 
@TopLimit = @TopLimit 

这种方法允许方便地添加新的筛选要求

+0

感谢Stas - 在我看来,你已经采用了将所有20个参数(或者说很多参数)传递给调用存储过程的代码的方法,对每个不需要的参数都使用null参数。这与我在顶级代码中动态构建sql的方式大致相似。但是,我试图通过传递一个选择参数来实现这一点。 – David 2011-03-27 20:33:11

0

您可以创建一个ISearchOption接口,提供必要的选项给DAL。您可以为GetRecords(ISearchOption options)提供常见的重载,构造一个内部ISearchOption实例并将其传递给GetRecords()过载。

另一种选择是使用LINQ-to-SQL。然后,您可以直接将该表作为IQueryable公开。客户端代码可以根据需要完全自由地过滤表格。