(ASP.NET) ASP.NET (2007 год)

Классические Business Logic Layer

На этой страничке я расскажу как писать собственные бизнес-объекты для AsP2-страничек. На эту тему есть как-бы статейка в MSDN, однако понять по ней что это такое именно - непросто. У меня на сайте также описан один из созданных мною еще в 2005-году бизнес-обьект на базе спец-коллекций.


Для того, чтоб написать нормальный (который я называю классическим BLL) надо чтоб он вызывался из ObjectDataSource, размещенного на страничке. И чтобы контролы могли БЕЗ дополнительных ухищрений быть просто привязаны к этому ObjectDataSource. Для примера рассмотрим вот такую страничку, на которой выводится списочек курсов учебного заведения.




Формируется этот списочек весьма прихотливо - десять принципиально разных режимов его формирования. Плюс коррелированный справа списочек воскресных занятий, соответствующих основному списочку. Самая правая табличка внизу - она как раз и показывает режим работы BLL - для демонстрационных целей. В данном случае - страничка сформировала режим работы BLL - FillBySemesterAndMainSubCategry. C таким коррелированным списочком (который находится чуть выше отладочной панели) я толкнулся впервые и тут тоже есть пара интересных моментов, которые мы посмотрим позже.

Вообще на этом хомячке я описал технику построения и более хитрых BLL - в том числе таких, где перечень режимов работы можно расширять и расширять с помощью плагинов. Разумеется, любой из этих бизнес-обьектов можно вызывать не только со страничек, но из любого ASP2-класса, а тот, что написан на базе спецколлекций - вообще не использует Session и был написан ЕДИНЫМ библиотечным модулем для виндузовых и вэб-приложений.


Но сначала начнем с элементарного. Для того, чтобы контролы могли получать рекордсеты при посредничестве ObjectDataSource - наш BLL должен обязательно хранить в себе экземпляр ДатаТабле и отдавать на него ссылку именно тем методом, который мы укажем в ObjectDataSource.




Как видите, у моего бизнес обьекта есть два метода, возвращающие данные - GetCourseList (для основного списочка) и GetSamSeminarList (для связанного списочки воскресных семинаров по этим же темам). В обоих случаях возврат данных происходит в виде типизированной таблички dsCourses.CourseDataTable. Это, так сказать, внешний интерфейс нашего бизнес обьекта.




Теперь посмотрим его внутреннее устройство. На самом деле есть несколько способов передачи параметров в Бизнес-обьект. Один из них - в ObjectDataSource.Selecting есть параметр e.Arguments, через который и передаются параметры для ObjectDataSource. Но я чаще передаю параметры в бизнес-обьекты через Session. Мне кажется так удобнее - тем более единажду установленный Session, например, с номером семестра, можно использовать В РАЗНЫХ бизнес-обьектах без дополнительного кода, а у меня их только для работы этой страничке четыре штуки.

Итак, мы остановились на том, что параметры для работы Бизнес-обьекта будут сформированы из Session, и по ним бизнес-объект сформирует выходной рекордсет. Теперь начало класса BLL очевидно.

00001:     Public Enum Sort_Order
00002:         Kursnummer = 1
00003:         Stufe = 2
00004:         Uhrzeit = 3
00005:         DozentIn = 4
00006:     End Enum
00007: 
00008:     Public Enum Course_Mode
00009:         FillByNummer = 1
00010:         FillBySemester = 2
00011:         FillByNummerAndSemester = 3
00012:         FillBySemesterAndMainSubCategry = 4
00013:         FillByLector = 5
00014:         FillBySemesterAndLector = 6
00015:         FillBySemesterAndLectorAndMainSubCategory = 7
00016:         FillSamBySemester = 8
00017:         FillSamBySemesterAndMainSubCategory = 9
00018:         FillSamBySemesterAndNummer = 10
00019:     End Enum
00020: 

Соотвественно обращение к нашему бизнес-обекту со странички будет выглядеть примерно так:




Далее идет определение класса и пара методов, позволяющих со стороны странички наложить фильтр на наш кеш с данными и пересортировать его. Обратите внимание на тртибут класса System.ComponentModel.DataObject, позволяющий кликнуть галочку "show only data component" и из великого множества различных коллекций в этом проекте отобрать НЕСКОЛЬКО .

00021:     <System.ComponentModel.DataObject()> _
00022:     Public Class BLLCourseList
00023: 
00024:         Dim Cn As New dsCourses.CourseDataTable
00025:         Dim CnMain As New dsCourses.CourseDataTable 'cphMainContent
00026:         Dim CnSecond As New dsCourses.CourseDataTable 'cphSecondaryContent
00027:         Dim CnMainDV As DataView = Cn.DefaultView
00028:         Dim CnSecondDV As DataView = New DataView(Cn)
00029:         Dim CnTa As New dsCoursesTableAdapters.CourseNewTableAdapter
00030:         Dim CnCourseFilter As Course_Filter
00031:         Dim CnOrder As Sort_Order
00032:         Dim CnCourseMode As Course_Mode
00033:         Dim CnLectorID As String
00034:         Dim CnSemesterID As String
00035:         Dim CnMainCategoryID As String
00036:         Dim CnSubCategoryID As String
00037:         Dim CnCourseID As String
00038: 
00039:         Private Enum Course_Filter
00040:             OnlySamstagsSeminar = 1
00041:             WithoutSamstagsSeminar = 2
00042:             NoFilter = 3
00043:         End Enum
00044: 
00045:         ''' <summary>
00046:         ''' Filling DataSet for type, specified in Session("CourseListMode") - one or more courses
00047:         ''' </summary>
00048:         Public Sub New()
00049:             Me.Refresh()
00050:         End Sub
00051:         Private Sub ImposeFilter(ByVal FilterType As Course_Filter)
00052:             Select Case FilterType
00053:                 Case Course_Filter.OnlySamstagsSeminar
00054:                     CnMainDV.RowFilter = "Samstagsseminar='true'"
00055:                 Case Course_Filter.WithoutSamstagsSeminar
00056:                     CnMainDV.RowFilter = "Samstagsseminar='false'"
00057:             End Select
00058:         End Sub
00059:         Private Sub ReSort(ByVal OrderID As Sort_Order)
00060:             Select Case OrderID
00061:                 Case Sort_Order.Kursnummer
00062:                     CnMainDV.Sort = "Kursnummer"
00063:                 Case Sort_Order.Stufe
00064:                     CnMainDV.Sort = "StufeOrder desc"
00065:                 Case Sort_Order.Uhrzeit
00066:                     CnMainDV.Sort = "DayOfWeek"
00067:                 Case Sort_Order.DozentIn
00068:                     CnMainDV.Sort = "Nachname, Vorname"
00069:             End Select
00070:         End Sub

Обратите также внимание на то, что собственно формирование ДатаСета вынесено в отдельный метод Refresh, ибо созданием бизнес обьектов управляет сам движок ASP2, а вот переформировать рекордсет нам может потребоваться в любой момент. Правда для этого надо на страничке иметь на него ссылку. Это важно. Ибо именно эта ссылка позволяет зацепиться за бизнес, обьект и вызвать у него ВТОРОЙ метод, в данном случае для коррелированного списочка справа.

Собственно получить ссылку на бизнес-объект с главной странички можно так:




Теперь посмотрим собственно сам метод Refresh, готовящий данные.

00071:         ''' <summary>
00072:         ''' Filling DataSet for type, specified in Session("CourseListMode") - one or more courses and
00073:         ''' return TWO datatable - Main (on GetCourseList) and Side(Samstag) on GetSamSeminarList
00074:         ''' </summary>
00075:         Public Sub Refresh()
00076:             If Not (HttpContext.Current.Session("CourseListMode") Is Nothing) Then
00077:                 '
00078:                 Dim T As Course_Mode = CInt(HttpContext.Current.Session("CourseListMode"))
00079:                 CnCourseMode = T
00080:                 '
00081:                 CnSemesterID = HttpContext.Current.Session("SemesterID")
00082:                 CnMainCategoryID = HttpContext.Current.Session("MainCategoryID")
00083:                 CnSubCategoryID = HttpContext.Current.Session("SubCategoryID")
00084:                 CnLectorID = HttpContext.Current.Session("LectorID")
00085:                 CnCourseID = HttpContext.Current.Session("CourseID")
00086:                 CnOrder = CInt(HttpContext.Current.Session("SortOrder"))
00087:                 If CnOrder = 0 Then CnOrder = Sort_Order.Kursnummer
00088:                 '
00089:                 CnSecondDV.RowFilter = "Samstagsseminar='true'"
00090:                 CnSecondDV.Sort = "Kursnummer"
00091:                 '
00092:                 CnTa.ClearBeforeFill = True
00093:                 Select Case T
00094:                     Case Course_Mode.FillBySemesterAndMainSubCategry
00095:                         If Not (HttpContext.Current.Session("MainCategoryID") Is Nothing) And _
00096:                         Not (HttpContext.Current.Session("SemesterID") Is Nothing) And _
00097:                         Not (HttpContext.Current.Session("SubCategoryID") Is Nothing) Then
00098:                             Try
00099:                                 CnTa.FillBySemesterAndMainSubCategry(Cn, New Guid(HttpContext.Current.Session("SemesterID").ToString), New Guid(HttpContext.Current.Session("MainCategoryID").ToString), New Guid(HttpContext.Current.Session("SubCategoryID").ToString))
00100:                             Catch ex As System.Data.ConstraintException
00101:                             End Try
00102:                             ImposeFilter(Course_Filter.WithoutSamstagsSeminar)
00103:                         Else
00104:                             Throw New Exception("Session(""MainCategoryID""), Session(""SemesterID""), Session(""SubCategoryID"") are need for use class ""BLLCourseList"" with Session(""CourseListMode"")=FillBySemesterAndMainSubCategry. ")
00105:                         End If
00106:                         '
00107:                         Try
00108:                             CnSecond.Merge(CnSecondDV.ToTable)
00109:                         Catch ex As System.Data.ConstraintException
00110:                         End Try
00111: 
00112:                     Case Course_Mode.FillByNummer
00113:                         If Not (HttpContext.Current.Session("CourseID") Is Nothing) Then
00114:                             Try
00115:                                 CnTa.FillByNummer(Cn, HttpContext.Current.Session("CourseID").ToString)
00116:                             Catch ex As System.Data.ConstraintException
00117:                             End Try
00118:                             ImposeFilter(Course_Filter.NoFilter)
00119:                         Else
00120:                             Throw New Exception("Session(""CourseID"") are need for use class ""BLLCourseList"" with Session(""CourseListMode"")=Course. ")
00121:                         End If
00122:                         If HttpContext.Current.Session("SemesterID") Is Nothing Then
00123:                             Dim CMD As New siSMWeb.ExecSQL_RDR()
00124:                             Dim rdr = CMD.ExecSQL("dbo.nc_SemesterSelectCurrent")
00125:                             If rdr.Read Then HttpContext.Current.Session("SemesterID") = rdr("SemesterID").ToString
00126:                         End If
00127:                         'В этом режиме боковую панель получим не фильтрацией из главной, а вообще заново
00128:                         Try
00129:                             CnTa.FillSamBySemester(CnSecond, New Guid(HttpContext.Current.Session("SemesterID").ToString))
00130:                         Catch ex As System.Data.ConstraintException
00131:                         End Try
00132: 
00133:                     Case Course_Mode.FillByNummerAndSemester
00134:                         If Not (HttpContext.Current.Session("CourseID") Is Nothing) And _
00135:                         Not (HttpContext.Current.Session("SemesterID") Is Nothing) Then
00136:                             Try
00137:                                 CnTa.FillByNummerAndSemester(Cn, HttpContext.Current.Session("CourseID").ToString, New Guid(HttpContext.Current.Session("SemesterID").ToString))
00138:                             Catch ex As System.Data.ConstraintException
00139:                             End Try
00140:                             ImposeFilter(Course_Filter.NoFilter)
00141:                         Else
00142:                             Throw New Exception("Session(""CourseID""), Session(""SemesterID"") are need for use class ""BLLCourseList"" with Session(""CourseListMode"")=SemesterAndCourse. ")
00143:                         End If
00144:                         'В этом режиме боковую панель получим не фильтрацией из главной, а вообще заново
00145:                         Try
00146:                             CnTa.FillSamBySemester(CnSecond, New Guid(HttpContext.Current.Session("SemesterID").ToString))
00147:                         Catch ex As System.Data.ConstraintException
00148:                         End Try
00149: 
00150:                     Case Course_Mode.FillBySemester
00151:                         If Not (HttpContext.Current.Session("SemesterID") Is Nothing) Then
00152:                             Try
00153:                                 CnTa.FillBySemester(Cn, New Guid(HttpContext.Current.Session("SemesterID").ToString))
00154:                             Catch ex As System.Data.ConstraintException
00155:                             End Try
00156:                             ImposeFilter(Course_Filter.WithoutSamstagsSeminar)
00157:                         Else
00158:                             Throw New Exception("Session(""SemesterID"") are need for use class ""BLLCourseList"" with Session(""CourseListMode"")=Semester. ")
00159:                         End If
00160:                         '
00161:                         Try
00162:                             CnSecond.Merge(CnSecondDV.ToTable)
00163:                         Catch ex As System.Data.ConstraintException
00164:                         End Try
00165: 
00166:                     Case Course_Mode.FillByLector
00167:                         If Not (HttpContext.Current.Session("LectorID") Is Nothing) Then
00168:                             Try
00169:                                 CnTa.FillByLector(Cn, New Guid(HttpContext.Current.Session("LectorID").ToString))
00170:                             Catch ex As System.Data.ConstraintException
00171:                             End Try
00172:                             ImposeFilter(Course_Filter.NoFilter)
00173:                         Else
00174:                             Throw New Exception("Session(""LectorID"") are need for use class ""BLLCourseList"" with Session(""CourseListMode"")=Course_Mode.Lector. ")
00175:                         End If
00176:                         '
00177:                         Try
00178:                             CnSecond.Merge(CnSecondDV.ToTable)
00179:                         Catch ex As System.Data.ConstraintException
00180:                         End Try
00181: 
00182:                     Case Course_Mode.FillBySemesterAndLector
00183:                         If Not (HttpContext.Current.Session("SemesterID") Is Nothing) And _
00184:                         Not (HttpContext.Current.Session("LectorID") Is Nothing) Then
00185:                             Try
00186:                                 CnTa.FillBySemesterAndLector(Cn, New Guid(HttpContext.Current.Session("SemesterID").ToString), New Guid(HttpContext.Current.Session("LectorID").ToString))
00187:                             Catch ex As System.Data.ConstraintException
00188:                             End Try
00189:                             ImposeFilter(Course_Filter.NoFilter)
00190:                         Else
00191:                             Throw New Exception("Session(""LectorID""), Session(""SemesterID"") are need for use class ""BLLCourseList"" with Session(""CourseListMode"")=Course_Mode.SemesterAndLector. ")
00192:                         End If
00193:                         '
00194:                         Try
00195:                             CnSecond.Merge(CnSecondDV.ToTable)
00196:                         Catch ex As System.Data.ConstraintException
00197:                         End Try
00198: 
00199:                     Case Course_Mode.FillBySemesterAndLectorAndMainSubCategory
00200:                         If Not (HttpContext.Current.Session("SemesterID") Is Nothing) And _
00201:                             Not (HttpContext.Current.Session("LectorID") Is Nothing) And _
00202:                             Not (HttpContext.Current.Session("MainCategoryID") Is Nothing) And _
00203:                             Not (HttpContext.Current.Session("SubCategoryID") Is Nothing) Then
00204:                             Try
00205:                                 CnTa.FillBySemesterAndLectorAndMainSubCategory(Cn, New Guid(HttpContext.Current.Session("SemesterID").ToString), New Guid(HttpContext.Current.Session("LectorID").ToString), New Guid(HttpContext.Current.Session("MainCategoryID").ToString), New Guid(HttpContext.Current.Session("SubCategoryID").ToString))
00206:                             Catch ex As System.Data.ConstraintException
00207:                             End Try
00208:                             ImposeFilter(Course_Filter.NoFilter)
00209:                         Else
00210:                             Throw New Exception("Session(""LectorID""), Session(""SemesterID""), Session(""MainCategoryID""), Session(""SubCategoryID"") are need for use class ""BLLCourseList"" with Session(""CourseListMode"")=Course_Mode.FillBySemesterAndLectorAndMainSubCategory. ")
00211:                         End If
00212:                         '
00213:                         Try
00214:                             CnSecond.Merge(CnSecondDV.ToTable)
00215:                         Catch ex As System.Data.ConstraintException
00216:                         End Try
00217: 
00218:                     Case Course_Mode.FillSamBySemester
00219:                         If Not (HttpContext.Current.Session("SemesterID") Is Nothing) Then
00220:                             Try
00221:                                 CnTa.FillSamBySemester(Cn, New Guid(HttpContext.Current.Session("SemesterID").ToString))
00222:                             Catch ex As System.Data.ConstraintException
00223:                             End Try
00224:                             ImposeFilter(Course_Filter.OnlySamstagsSeminar)
00225:                         Else
00226:                             Throw New Exception("Session(""SemesterID"") are need for use class ""BLLCourseList"" with Session(""CourseListMode"")=Samstags. ")
00227:                         End If
00228:                         '
00229:                         Try
00230:                             CnSecond.Merge(CnSecondDV.ToTable)
00231:                         Catch ex As System.Data.ConstraintException
00232:                         End Try
00233: 
00234:                     Case Course_Mode.FillSamBySemesterAndMainSubCategory
00235:                         If Not (HttpContext.Current.Session("MainCategoryID") Is Nothing) And _
00236:                         Not (HttpContext.Current.Session("SemesterID") Is Nothing) And _
00237:                         Not (HttpContext.Current.Session("SubCategoryID") Is Nothing) Then
00238:                             Try
00239:                                 CnTa.FillSamBySemesterAndMainSubCategory(Cn, New Guid(HttpContext.Current.Session("SemesterID").ToString), New Guid(HttpContext.Current.Session("MainCategoryID").ToString), New Guid(HttpContext.Current.Session("SubCategoryID").ToString))
00240:                             Catch ex As System.Data.ConstraintException
00241:                             End Try
00242:                             ImposeFilter(Course_Filter.OnlySamstagsSeminar)
00243:                         Else
00244:                             Throw New Exception("Session(""MainCategoryID""), Session(""SemesterID""), Session(""SubCategoryID"") are need for use class ""BLLCourseList"" with Session(""CourseListMode"")=FillSamBySemesterAndMainSubCategory. ")
00245:                         End If
00246:                         '
00247:                         Try
00248:                             CnSecond.Merge(CnSecondDV.ToTable)
00249:                         Catch ex As System.Data.ConstraintException
00250:                         End Try
00251: 
00252:                     Case Course_Mode.FillSamBySemesterAndNummer
00253:                         If Not (HttpContext.Current.Session("CourseID") Is Nothing) And _
00254:                         Not (HttpContext.Current.Session("SemesterID") Is Nothing) Then
00255:                             Try
00256:                                 CnTa.FillSamBySemesterAndKursnummer(Cn, New Guid(HttpContext.Current.Session("SemesterID").ToString), HttpContext.Current.Session("CourseID"))
00257:                             Catch ex As System.Data.ConstraintException
00258:                             End Try
00259:                             ImposeFilter(Course_Filter.OnlySamstagsSeminar)
00260:                         Else
00261:                             Throw New Exception("Session(""MainCategoryID""), Session(""SemesterID""), Session(""SubCategoryID"") are need for use class ""BLLCourseList"" with Session(""CourseListMode"")=FillSamBySemesterAndMainSubCategory. ")
00262:                         End If
00263:                         'В этом режиме боковую панель получим не фильтрацией из главной, а вообще заново
00264:                         Try
00265:                             CnTa.FillSamBySemester(CnSecond, New Guid(HttpContext.Current.Session("SemesterID").ToString))
00266:                         Catch ex As System.Data.ConstraintException
00267:                         End Try
00268: 
00269:                 End Select
00270:                 'теперь пересортируем и отфильтруем курсы в главную таблу
00271:                 If CnMainDV.Count > 1 Then Call ReSort(CnOrder)
00272:                 Try
00273:                     CnMain.Merge(CnMainDV.ToTable)
00274:                 Catch ex As System.Data.ConstraintException
00275:                 End Try
00276:             Else
00277:                 Throw New Exception("Session(""CourseListMode"") are need for use class ""BLLCourseList"". ")
00278:             End If
00279:         End Sub

Как видите, это довольно тривиальный код, компонующий параметры для обращения к методам заполнения рекордсета и реализующий все десять способов формирования основного и дополнительного списочков.

Завершающий фрагмент этого BLL - собственно методы, возвращающий данные для ObjectDataSource:

00280:         ''' <summary>
00281:         ''' Return One or More sorted and filtered Courses (параметры сюда при желании можно передать через e.Arguments события странички CourseListObj_Selecting
00282:         ''' </summary>
00283:         Public Function GetCourseList() As dsCourses.CourseDataTable
00284:             GetCourseList = CnMain
00285:         End Function
00286:         ''' <summary>
00287:         ''' Return SamSeminar, соответствующие главному списку
00288:         ''' </summary>
00289:         Public Function GetSamSeminarList() As dsCourses.CourseDataTable
00290:             GetSamSeminarList = CnSecond
00291:         End Function
00292:     End Class

Как видите, все довольно просто. Теперь посмотрим, как именно устроен наш ДатаСет, в котором перечислены методы отбора из базы:




В данном случае ДатаСет содержит несколько таблиц для всех Бизнес-обьектов этой странички.


Теперь посмотрим как эти отборы устроены на уровне SQL. Разумеется, такое счастье выпадает не всегда и обычно отборы сложные-пресложные и совершенно не похожи друг на друга. Но в этом случае мне повезло. А возможно я сам организовал себе везение, создав такую вьюшку:

00001: ALTER View [dbo].[CourseList]
00002: as
00003: select
00004: [Course].[CourseID],
00005: [Course].[DefaultRoomID],
00006: [Course].[DefaultDozentID],
00007: [Course].[MainCategoryID],
00008: [Course].[SubCategoryID],
00009: [Course].[SemesterID],
00010: [Course].[CourseString],
00011: [Course].[Kursnummer],
00012: [Course].[Kursbezeichnung],
00013: [Course].[Kursbeschreibung],
00014: [Course].[Kursbeschreibung_lang],
00015: [Course].[Kursstunden],
00016: [Course].[Kurspreis],
00017: [Course].[Skript],
00018: [Course].[Skriptpreis],
00019: [Course].[DefaultKursbeginnZeit],
00020: [Course].[DefaultKursendeZeit],
00021: [Course].[Kursbemerkungen],
00022: [Course].[Lehrmittel],
00023: [Course].[Spalte1Bemerkungen],
00024: [Course].[Spalte2Bemerkungen],
00025: [Course].[Status],
00026: [Course].[Stufe],
00027: [Course].[SortIndex],
00028: [Course].[Eroeffnungsdatum],
00029: [Course].[EroeffnetVon],
00030: [Course].[Mutationsdatum],
00031: [Course].[MutiertVon],
00032: [Course].[AnzTeilnehmer],
00033: [Course].[MinTeilnehmer],
00034: [Course].[MaxTeilnehmer],
00035: [Course].[Samstagsseminar],
00036: [Course].[ErfolgskontoDebitoren],
00037: [Semester].[Semester],
00038: [Room].[Raumnummer],
00039: [Room].[Ort],
00040: [Contact].[Vorname],
00041: [Contact].[Nachname],
00042: left([Course].[DefaultKurstag],2) as DefaultKurstag,
00043: null as SamSemDatum,
00044: case [Course].[DefaultKurstag]
00045: when 'Montag' then 1
00046: when 'Dienstag' then 2
00047: when 'Mittwoch' then 3
00048: when 'Donnerstag' then 4
00049: when 'Freitag' then 5
00050: when 'Samstag' then 6
00051: when 'Sonntag' then 7
00052: end as [DayOfWeek],
00053: case 
00054: when len([Course].[Stufe])>0 then [Course].[Stufe]
00055: else 'Z'
00056: end as [StufeOrder]
00057: FROM   Course 
00058: JOIN Contact ON Course.DefaultDozentID = Contact.ContactID 
00059: JOIN Semester ON Course.SemesterID = Semester.SemesterID 
00060: JOIN Room ON Course.DefaultRoomID = Room.RoomID
00061: where  Samstagsseminar='false' and ShowWeb = N'true'
00062: 
00063: union all
00064: 
00065: select
00066: [Course].[CourseID],
00067: [Course].[DefaultRoomID],
00068: [Course].[DefaultDozentID],
00069: [Course].[MainCategoryID],
00070: [Course].[SubCategoryID],
00071: [Course].[SemesterID],
00072: [Course].[CourseString],
00073: [Course].[Kursnummer],
00074: [Course].[Kursbezeichnung],
00075: [Course].[Kursbeschreibung],
00076: [Course].[Kursbeschreibung_lang],
00077: [Course].[Kursstunden],
00078: [Course].[Kurspreis],
00079: [Course].[Skript],
00080: [Course].[Skriptpreis],
00081: [Course].[DefaultKursbeginnZeit],
00082: [Course].[DefaultKursendeZeit],
00083: [Course].[Kursbemerkungen],
00084: [Course].[Lehrmittel],
00085: [Course].[Spalte1Bemerkungen],
00086: [Course].[Spalte2Bemerkungen],
00087: [Course].[Status],
00088: [Course].[Stufe],
00089: [Course].[SortIndex],
00090: [Course].[Eroeffnungsdatum],
00091: [Course].[EroeffnetVon],
00092: [Course].[Mutationsdatum],
00093: [Course].[MutiertVon],
00094: [Course].[AnzTeilnehmer],
00095: [Course].[MinTeilnehmer],
00096: [Course].[MaxTeilnehmer],
00097: [Course].[Samstagsseminar],
00098: [Course].[ErfolgskontoDebitoren],
00099: [Semester].[Semester],
00100: [Room].[Raumnummer],
00101: [Room].[Ort],
00102: [Contact].[Vorname],
00103: [Contact].[Nachname],
00104: left([Course].[DefaultKurstag],2) as DefaultKurstag,
00105: case 
00106: when isnull(SamSemDatum1,0)=0 then ''
00107: else convert(nvarchar,SamSemDatum1,5)
00108: end 
00109: +
00110: case 
00111: when isnull(SamSemDatum2,0)=0 then ''
00112: else ' / ' + convert(nvarchar,SamSemDatum2,5)
00113: end 
00114: +
00115: case 
00116: when isnull(SamSemDatum3,0)=0 then ''
00117: else ' / ' + convert(nvarchar,SamSemDatum3,5)
00118: end 
00119: +
00120: case 
00121: when isnull(SamSemDatum4,0)=0 then ''
00122: else ' / ' + convert(nvarchar,SamSemDatum4,5)
00123: end 
00124: +
00125: case 
00126: when isnull(SamSemDatum5,0)=0 then ''
00127: else ' / ' + convert(nvarchar,SamSemDatum5,5)
00128: end 
00129: +
00130: case 
00131: when isnull(SamSemDatum6,0)=0 then ''
00132: else ' / ' + convert(nvarchar,SamSemDatum6,5)
00133: end 
00134: as SamSemDatum,
00135: case [Course].[DefaultKurstag]
00136: when 'Montag' then 1
00137: when 'Dienstag' then 2
00138: when 'Mittwoch' then 3
00139: when 'Donnerstag' then 4
00140: when 'Freitag' then 5
00141: when 'Samstag' then 6
00142: when 'Sonntag' then 7
00143: end as [DayOfWeek],
00144: case 
00145: when len([Course].[Stufe])>0 then [Course].[Stufe]
00146: else 'Z'
00147: end as [StufeOrder]
00148: FROM   Course 
00149: JOIN Contact ON Course.DefaultDozentID = Contact.ContactID 
00150: JOIN Semester ON Course.SemesterID = Semester.SemesterID 
00151: JOIN Room ON Course.DefaultRoomID = Room.RoomID
00152: where  Samstagsseminar='true' and ShowWeb = N'true'

Здесь есть пара моментов, которые могут вызвать гомерический хохот у настоящего гурмана - например запоминание логических величин True/False в базе в виде тектовых строк. Разумееется, вы понимаете, что структуру базы разрабатывал не я... Обратите внимание, как я создал дополнительные столбцы на уровне SQL, чтобы предельно упростить BLL и свести сортировку в ДатаСетах к стандартному методу.

Так вот, создав такую вьюшку, я могу делать множество отборов весьма единообразно - примерно так:

00001: ALTER PROCEDURE [dbo].[nc_CourseSamSelectBySemesterAndMainSubCategory]
00002: @SemesterID uniqueidentifier,
00003: @MainCategoryID uniqueidentifier,
00004: @SubCategoryID uniqueidentifier
00005: AS
00006: SELECT * FROM CourseList WHERE Samstagsseminar='true' and SemesterID=@SemesterID 
00007: and MainCategoryID=@MainCategoryID and SubCategoryID=@SubCategoryID
00008: order by Kursnummer
00009: 
00010: 
00011: ALTER PROCEDURE [dbo].[nc_CourseSamSelectBySemesterAndKursnummer]
00012: @SemesterID uniqueidentifier,
00013: @Kursnummer nvarchar(50)
00014: AS
00015: SELECT * FROM CourseList 
00016: WHERE Samstagsseminar='true' and SemesterID=@SemesterID and Kursnummer=@Kursnummer
00017: order by Kursnummer
00018: 
00019: 
00020: ALTER PROCEDURE [dbo].[nc_CourseSamSelectBySemester]
00021: @SemesterID uniqueidentifier
00022: AS
00023: SELECT * FROM CourseList 
00024: WHERE Samstagsseminar='true' and SemesterID=@SemesterID
00025: order by Kursnummer
00026: 
00027: 
00028: ALTER PROCEDURE [dbo].[nc_CourseSelectByNummer]
00029: @CourseID nvarchar(50)
00030: AS
00031: SELECT * FROM CourseList WHERE  Kursnummer = @CourseID
00032: 
00033: 
00034: ALTER PROCEDURE [dbo].[nc_CourseSelectBySemesterAndLectorAndMainSubCategory]
00035: @SemesterID uniqueidentifier,
00036: @LectorID uniqueidentifier,
00037: @MainCategoryID uniqueidentifier,
00038: @SubCategoryID uniqueidentifier
00039: AS
00040: SELECT * FROM CourseList 
00041: WHERE SemesterID = @SemesterID 
00042: and DefaultDozentID=@LectorID 
00043: and MainCategoryID=@MainCategoryID
00044: and SubCategoryID=@SubCategoryID
00045: 

... И так далее. Как видите, процедур много, но для их написания вообще думать не требуется. Это не единственное достоинство. Второе - то, что оптимизатор видит что параметры отборов разные и строит планы отборов по-разному в каждом их отборов. Но, разумеется, такое счастье выпадает далеко не в каждом проекте - значительно чаще все же эти процедуры совершенно непохожи друг на друга.



Comments ( )
Link to this page: //www.vb-net.com/asp2/23/index.htm
< THANKS ME>