[英]Move Data Access logic from the business layer to the data access layer
我正在做一個具有數據訪問層(DAL)的asp.net mvc應用程序。 完成90%的數據庫CRUD代碼后,我問自己是否需要業務層。
但是我應該放在那兒呢? 例如,我在DAL中的所有CRUD方法都不是單個選擇。 大多數時候,我會執行許多join + sql聚合函數。 只是說我使用ADO.NET,沒有存儲過程/觸發器。
然后我再次問自己,這種方法是否屬於業務層:
/// <summary>
/// Creates a testplan with all teststeps and their default values for a certain template
/// </summary>
/// <param name="testplan"></param>
/// <returns>true if transaction was successfull else false</returns>
public void CreateTestplan(Testplan testplan)
{
try
{
using (var con = new SqlConnection(_connectionString))
using (var trans = new TransactionScope())
{
con.Open();
_testplanDataProvider.AddTestplan(testplan,con);
_testplanDataProvider.CreateTeststepsForTestplan(testplan.Id, testplan.TemplateId,con);
trans.Complete();
}
}
catch (SqlException ex)
{
ExceptionManager.HandleException(ex);
}
}
該方法實際上是在DAL中調用其他兩個方法。
現在我問我自己,為什么要引入一個額外的業務層,當我可以將CreateTestplan方法也放在這兩個方法中的所有代碼中(包括AddTestplan + CreateTeststepsForTestplan)時,將它放在TestplanDataProvider類中。
你怎么看? 這是一個好方法嗎?
我之所以這么問,是因為我認為CreateTestplan方法僅包含數據訪問邏輯。
更新 :
public void AddTestplan(Testplan testplan, SqlConnection con)
{
using (var cmd = new SqlCommand("INSERT INTO TESTPLAN (ReleaseId,TemplateId,CreatedAt,UserId,Name,Duration) VALUES (@ReleaseId,@TemplateId,@CreatedAt,@UserId,@Name,@Duration);Select Scope_Identity();", con))
{
var p1 = new SqlParameter("@ReleaseId", testplan.ReleaseId);
var p2 = new SqlParameter("@TemplateId", testplan.TemplateId);
var p3 = new SqlParameter("@CreatedAt", testplan.CreatedAt);
var p4 = new SqlParameter("@UserId", testplan.UserId);
var p5 = new SqlParameter("@Name", testplan.Name);
var p6 = new SqlParameter("@Duration", testplan.Duration);
cmd.Parameters.AddRange(new[] { p1, p2, p3, p4, p5, p6 });
testplan.Id = Convert.ToInt32(cmd.ExecuteScalar());
}
}
public void CreateTeststepsForTestplan(int testplanId, int templateId, SqlConnection con)
{
var teststeps = new List<Teststep>();
using (var selectCMD = new SqlCommand("SELECT ts.TeststepId, MAX(ts.CreatedAt)FROM Teststep ts INNER JOIN Unit u ON ts.UnitId = u.UnitId Where u.TemplateId = @TemplateId Group by TeststepId", con))
{
var p = new SqlParameter("@TemplateId", templateId);
selectCMD.Parameters.Add(p);
using (var reader = selectCMD.ExecuteReader())
{
Teststep teststep = null;
while (reader.Read())
{
teststep = new Teststep
{
Id = Convert.ToInt32(reader["TeststepId"]),
CreatedAt = Convert.ToDateTime(reader["CreatedAt"]),
};
teststeps.Add(teststep);
}
}
}
using (var insertCMD = new SqlCommand("INSERT INTO TestplanTeststep (TestplanId,TeststepId,TestState,ErrorText) VALUES (@TestplanId, @TeststepId, @TestState, @ErrorText)", con))
{
var p1 = new SqlParameter("@TeststepId", SqlDbType.Int);
var p2 = new SqlParameter("@CreatedAt", SqlDbType.DateTime);
var p3 = new SqlParameter("@TestplanId", testplanId);
var p4 = new SqlParameter("@ErrorText", DBNull.Value);
var p5 = new SqlParameter("@ErrorScreenshot", DBNull.Value);
var p6 = new SqlParameter("@TestState", (int)Teststep.TeststepTestState.Untested);
insertCMD.Parameters.AddRange(new[] { p1, p2, p3, p4, p5 });
foreach (Teststep step in teststeps)
{
p1.Value = step.Id;
p2.Value = step.CreatedAt;
insertCMD.ExecuteNonQuery();
}
}
}
阻止對BLL進行數據訪問的一個好理由是,您可以在對業務邏輯進行最小更改的情況下切換數據庫或數據庫框架。
例如,如果您將所有與ADO.NET相關的代碼移到DAL,然后又決定使用Entity Framework,則只會更改DAL,而不會更改BLL。
當然,如果您的業務邏輯很少,而BLL只是將工作移交給DAL,您可能不會從擁有單獨的層中獲益。 對於非常瑣碎的應用程序可能會出現這種情況,但也可能表明DAL中隱藏了業務邏輯。
我知道通常公認的最佳實踐是將DAC與BL分開,但是我認為,如果您正在使用L2S或Entity框架之類的東西,那么您已經擁有DAL,並且您的業務邏輯可以納入這些的部分定義類。 無需在此之上添加另一個DAL。 我什至會認為ADO是構成DAL的抽象。 順便說一句,由於您使用的是海峽ADO,因此您可能想看看Dapper。 這是最小且快速的DAL。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.