我已经编写了一段时间,但仍然认为自己是初学者。我使用非常简单的ADO.NET类和内置的SQL语句。我想听听社群关于我做错了什么以及如何改进的建议,以及建议的后续步骤是将我的编码纳入现行标准。
我真的很想尝试使用EF,虽然我似乎无法找到适合我的BLL和DAL类的教程,所以会喜欢指向正确方向的指针。
基本上如果我有礼物,我会创建一个礼物类(BLL \ Gift.cs):
using MyProject.DataAccessLayer;
namespace MyProject.BusinessLogicLayer
{
public class Gift
{
public int GiftID { get; set; }
public string GiftName { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public static Gift GetGiftByID(int GiftID)
{
GiftDAL dataAccessLayer = new GiftDAL();
return dataAccessLayer.GiftsSelectByID(GiftID);
}
public void DeleteGift(Gift myGift)
{
GiftDAL dataAccessLayer = new GiftDAL();
dataAccessLayer.DeleteGift(myGift);
}
public bool UpdateGift(Gift myGift)
{
GiftDAL dataAccessLayer = new GiftDAL();
return dataAccessLayer.UpdateGift(myGift);
}
public int InsertGift(string GiftName, string Description, decimal Price)
{
Gift myGift = new Gift();
myGift.GiftName = GiftName;
myGift.Description = Description;
myGift.Price = Price;
GiftDAL dataAccessLayer = new GiftDAL();
return dataAccessLayer.InsertGift(myGift);
}
}
}
然后我有一个DAL类,它保存我的连接字符串(DAL \ sqlDAL.css):
namespace MyProject.DataAccessLayer
{
public class SqlDataAccessLayer
{
public readonly string _connectionString = string.Empty;
public SqlDataAccessLayer()
{
_connectionString = WebConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString;
if (string.IsNullOrEmpty(_connectionString))
{
throw new Exception("No database connection String found");
}
}
}
}
然后是一个DAL类(DAL \ giftDAL.cs),其中我展示了几个方法(更新和删除):
using MyProject.BusinessLogicLayer;
namespace MyProject.DataAccessLayer
{
public class GiftDAL : SqlDataAccessLayer
{
public bool UpdateGift(Gift GifttoUpdate)
{
string UpdateString = "";
UpdateString += "UPDATE Gifts SET";
UpdateString += "GiftName = @GiftName";
UpdateString += ",Description = @Description ";
UpdateString += ",Price = @Price ";
UpdateString += " WHERE GiftID = @GiftID";
int RowsAffected = 0;
try
{
using (SqlConnection con = new SqlConnection(_connectionString))
{
using (SqlCommand cmd = new SqlCommand(UpdateString, con))
{
cmd.Parameters.AddWithValue("@GiftName", GifttoUpdate.GiftName);
cmd.Parameters.AddWithValue("@Description", GifttoUpdate.Description);
cmd.Parameters.AddWithValue("@Price ", GifttoUpdate.Price);
cmd.Parameters.AddWithValue("@GiftID", GifttoUpdate.GiftID);
con.Open();
RowsAffected = cmd.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Utils.LogError(ex.Message, ex.InnerException == null ? "N/A" : ex.InnerException.Message, ex.StackTrace);
}
return (RowsAffected == 1);
}
public void DeleteGift(Gift GifttoDelete)
{
string DeleteString = "";
DeleteString += "DELETE FROM GIFTS WHERE GIFTID = @GiftID";
try
{
using (SqlConnection con = new SqlConnection(_connectionString))
{
using (SqlCommand cmd = new SqlCommand(DeleteString, con))
{
cmd.Parameters.AddWithValue("@GiftID", GifttoDelete.GiftID);
con.Open();
cmd.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Utils.LogError(ex.Message, ex.InnerException == null ? "N/A" : ex.InnerException.Message, ex.StackTrace);
}
}
}
}
所以看一下,你会如何推荐我改进代码(如果我继续使用ADO.NET)以及我的下一步将学习EF - 还是有更好的替代方案?
干杯, 罗比
答案 0 :(得分:2)
如果您想坚持使用ADD.NET,那么为什么不从Microsoft Enterprise Library查看Data Application Block(当前版本是2011年5月5日) - 它将允许您编写供应商(MS-SQL / Oracle)等)中性代码很容易,大部分锅炉板编码都被包裹起来。
This可能是一个最简单/最短的教程,我可以帮助您入门。但是,MSDN链接有大量信息,请参阅关键场景部分以快速启动。
另一个建议是使用TransactionScope
来管理事务(而不是直接使用DbTransaction对象)。
所有我建议使用Entity Framework(或任何类似的OR映射工具 - 例如检查NHibernet),因为那样你就不必编写基本CRUD操作的典型代码了。就你的困境而言,这里有一个基本的代码片段,可以帮助你入门 - 我使用的是带有Code-First方法的EF 4.1,POCO实体和Fluent API:
实体:
public class Gift
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
}
数据访问层:
public class MyDbContext : DbContext
{
public DbSet<Gift> Gifts { get; set; }
public MyDbContext () : base("name=[ConnStringName]") {}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Fluent API to provide mapping - you may use attributes in entity class
var giftConfig = modelBuilder.Entity<Gift>();
giftConfig.Property(p => p.Id).HasColumnName("GiftID");
giftConfig.Property(p => p.Name).HasColumnName("GiftName");
giftConfig.Property(p => p.Description).HasColumnName("Description");
giftConfig.Property(p => p.Price).HasColumnName("Price");
giftConfig.HasKey(p => p.Id);
base.OnModelCreating(modelBuilder);
}
}
业务层:
public static class GiftManager
{
public static Gift GetById(int id)
{
using(var db = new MyDbContext())
{
return db.Gifts.Find(id);
}
}
public static void Add(Gift gift)
{
using(var db = new MyDbContext())
{
// do validation
...
db.Gifts.Add(gift);
// do auditing
...
db.SaveChanges();
}
}
public static void Update(Gift gift)
{
using(var db = new MyDbContext())
{
// do validation
...
var entity = db.Sessions.Find(gift.Id);
entity.Name = gift.Name;
entity.Description = gift.Description;
entity.Price = gift.Price;
// do auditing
...
db.SaveChanges();
}
}
}
答案 1 :(得分:2)
对我来说,一件重要的事情(对我来说)是一个可测试的课程。我在你的代码中看到了很多显式的对象构造。您的礼物BL类明确依赖于GiftDAL,这使得测试Gift类非常困难。尝试通过对GiftDAL(例如接口)进行抽象来减少类之间的耦合,并将其从外部提供给Gift(Dependency Injection)。
关于良好软件设计原则的好书是Clean Code by Robert C. Martin。他建立了SOLID原则。看看吧!
另外,请注意,您现在在业务逻辑类(或称为域模型)中包含持久性。这可以完成(Active Record),但是现在人们通常会选择不同的方法,将域模型与任何基础架构分开。宽泛的想法是:对象需要以某种方式存储的事实很重要,但对于业务逻辑本身并不重要,因此应尽可能分离关注点。对于.NET Object Relational Mapper或NHibernate,Entity Framework通常是OR映射器的两个示例。
答案 2 :(得分:0)
我有一个dal类,其方法只返回可绑定的对象,如datatable,List等。没有更多或更少。然后,所有业务逻辑在aspnet应用程序中的代码中自然发生。在大多数情况下制作支持对象的工作量太大而且过度杀伤。我对数据表和列表很满意。