贴子地址:
http://community.csdn.net/Expert/topic/5263/5263804.xml?temp=.772793其中LoveCherry(论成败,人生豪迈;大不了,重头再来!^_^) 回答道:==========================
很多人有这个困惑,分层后一旦要修改一个数据库字段需要把所有的层都修改一遍。往往这是由于你的指责不明确引起的。假如您的数据访问层仅仅做的是对某种数据库的数据访问操作,不涉及任何的业务,那么即使修改了表结构,数据访问层不需要修改任何代码。加入您的表现层仅仅是根据业务模型呈现数据,即使我们把字段名从Username修改成了name,由于业务层返回的还是原来的业务实体,表现层也不需要做任何改动。反之,您直接把从数据库中SELECT的记录通过DataSet返回给表现层,那么修改了数据表字段后肯定也要修改表现层。
===========================我纳闷:我的DataLayer层代码 public IList<AttackSpeedInfo> GetAttackSpeedList(string PlayerID, string OtherID, string Flag)
{
IList<AttackSpeedInfo> AllAttackSpeed = new List<AttackSpeedInfo>();
string procName = "sp_Attack";
DBManager.Open();
SqlDatabase db = DBManager.DB;
DbCommand Procdbcomm = db.GetStoredProcCommand(procName);
db.AddInParameter(Procdbcomm, "@PlayerID", DbType.String);
db.AddInParameter(Procdbcomm,"@OtherID",DbType.String);
db.AddInParameter(Procdbcomm,"@Flag",DbType.String); db.SetParameterValue(Procdbcomm, "@PlayerID", PlayerID);
db.SetParameterValue(Procdbcomm,"@OtherID",OtherID);
db.SetParameterValue(Procdbcomm,"@Flag",Flag); using (IDataReader reader = db.ExecuteReader(Procdbcomm))
{
while (reader.Read()) //玩家
{
AttackSpeedInfo attackspeed = new AttackSpeedInfo();//此处为Model对象
attackspeed.UserName = reader["UserName"].ToString();
attackspeed.T = float.Parse(reader["T"].ToString());
attackspeed.ID = reader["ID"].ToString();
AllAttackSpeed.Add(attackspeed);
} }
return AllAttackSpeed;
}问:如果我在数据库中修改UserName ,难道attackspeed.UserName = reader["UserName"].ToString();这个不能修改?我没有办法来理解他说的.请高人指点我
http://community.csdn.net/Expert/topic/5263/5263804.xml?temp=.772793其中LoveCherry(论成败,人生豪迈;大不了,重头再来!^_^) 回答道:==========================
很多人有这个困惑,分层后一旦要修改一个数据库字段需要把所有的层都修改一遍。往往这是由于你的指责不明确引起的。假如您的数据访问层仅仅做的是对某种数据库的数据访问操作,不涉及任何的业务,那么即使修改了表结构,数据访问层不需要修改任何代码。加入您的表现层仅仅是根据业务模型呈现数据,即使我们把字段名从Username修改成了name,由于业务层返回的还是原来的业务实体,表现层也不需要做任何改动。反之,您直接把从数据库中SELECT的记录通过DataSet返回给表现层,那么修改了数据表字段后肯定也要修改表现层。
===========================我纳闷:我的DataLayer层代码 public IList<AttackSpeedInfo> GetAttackSpeedList(string PlayerID, string OtherID, string Flag)
{
IList<AttackSpeedInfo> AllAttackSpeed = new List<AttackSpeedInfo>();
string procName = "sp_Attack";
DBManager.Open();
SqlDatabase db = DBManager.DB;
DbCommand Procdbcomm = db.GetStoredProcCommand(procName);
db.AddInParameter(Procdbcomm, "@PlayerID", DbType.String);
db.AddInParameter(Procdbcomm,"@OtherID",DbType.String);
db.AddInParameter(Procdbcomm,"@Flag",DbType.String); db.SetParameterValue(Procdbcomm, "@PlayerID", PlayerID);
db.SetParameterValue(Procdbcomm,"@OtherID",OtherID);
db.SetParameterValue(Procdbcomm,"@Flag",Flag); using (IDataReader reader = db.ExecuteReader(Procdbcomm))
{
while (reader.Read()) //玩家
{
AttackSpeedInfo attackspeed = new AttackSpeedInfo();//此处为Model对象
attackspeed.UserName = reader["UserName"].ToString();
attackspeed.T = float.Parse(reader["T"].ToString());
attackspeed.ID = reader["ID"].ToString();
AllAttackSpeed.Add(attackspeed);
} }
return AllAttackSpeed;
}问:如果我在数据库中修改UserName ,难道attackspeed.UserName = reader["UserName"].ToString();这个不能修改?我没有办法来理解他说的.请高人指点我
attackspeed.UserName = reader["UserName"].ToString();
试问:
按他的意思,在数据库中修改UserName为Name,他说他的数据层不用改..至少要改成:attackspeed.Name = reader["Name"].ToString();才对吧?
当在数据库中把UserName改成Name后,Model实体中也应该把对应的UserName改为Name吧?
这个字段修改了名字当然要改过来,你曲解了他的意思了,实行分层后修改了表结构可能需要改的只是数据层,而业务逻辑层涉及的和数据库表并没有直接关系,所以不用修改,而表示层是根据业务逻辑来呈现数据,所以也不用修改
如果你想UserName改成Name后实体类能自动映射,可以去看Castle
=========================================
说的正确。
另外最好不要用reader["字段名"]这样提取值。
我的逻辑层(BLL)中的代码为: private static readonly IAtlas dal = WebGame.DALFactory.DataAccess.CreateAtlas();
public AtlasInfo AtlasProperty(int AtlasID)
{
return dal.AtlasProperty(AtlasID); //几乎所有的方法都是这样子
}合理吗?我完全是按petshop4.0中的做法来处理的.
==============
不用这种,用哪种呢?难道还有其它更加方便的.请讲
{
while (reader.Read()) //玩家
{
AttackSpeedInfo attackspeed = new AttackSpeedInfo();//此处为Model对象
attackspeed.UserName = reader["UserName"].ToString();
attackspeed.T = float.Parse(reader["T"].ToString());
attackspeed.ID = reader["ID"].ToString();
AllAttackSpeed.Add(attackspeed);
}}==>
using (IDataReader reader = db.ExecuteReader(Procdbcomm))
{
while (reader.Read()) //玩家
{
AttackSpeedInfo attackspeed = new AttackSpeedInfo(reader);//此处为Model对象
//attackspeed.UserName = reader["UserName"].ToString();
//attackspeed.T = float.Parse(reader["T"].ToString());
//attackspeed.ID = reader["ID"].ToString();
//AllAttackSpeed.Add(attackspeed);
}}
然后实现AttackSpeedInfo 由reader构造
现在如果修改了数据库中的字段,你只需要修改AttackSpeedInfo类,也仅仅只需要修改它
==============
天天.你回答的太有道理了..!~~~~~~~~~~~~我一定要尝试去做...一针见血
===========
Castlep 这是啥来着?简单讲讲..
================
而且应该把IList<AttackSpeedInfo> 的组装提升到业务层来做
================我这种做法完全是按Microsoft中的petshop4.0来做的.贴一段petshop4.0代码给你看
public IList<ItemInfo> GetItemsByProduct(string productId) { IList<ItemInfo> itemsByProduct = new List<ItemInfo>(); SqlParameter parm = new SqlParameter(PARM_PRODUCT_ID, SqlDbType.VarChar, 10);
parm.Value = productId; //Execute the query against the database
using(SqlDataReader rdr = SqlHelper.ExecuteReader(SqlHelper.ConnectionStringLocalTransaction, CommandType.Text, SQL_SELECT_ITEMS_BY_PRODUCT, parm)) {
// Scroll through the results
while (rdr.Read()) {
ItemInfo item = new ItemInfo(rdr.GetString(0), rdr.GetString(1), rdr.GetInt32(2), rdr.GetDecimal(3), rdr.GetString(4), rdr.GetString(5), rdr.GetString(6), rdr.GetString(7));
//Add each item to the arraylist
itemsByProduct.Add(item);
}
}
return itemsByProduct;
}
 模仿别人的构架
很多人喜欢模仿微软的一些作品(PETSHOP等)作为自己项目的构架,确实这些作品给我们展示了很多新思想、优秀的设计模式和构架,但是我们不能盲目模仿,而应该根据自己的项目寻找最合适的构架。在一个对性能要求特别高而对扩展要求不高的项目上大量使用解耦框架,显然偏离了项目的初衷。而构架往往决定了整个项目的性能和可靠性,因此,在构架的选择上需要慎重,不要盲目模仿和追新。
 不断使用新的构架使得项目看上去很“先进”
我们知道,每一种构架都不是凭空产生的,而有很多人却喜欢凭空去使用它们。构架都是在实际的开发过程中遇到问题、解决问题发展而来的,每一种构架都有它们的优势和主要针对的问题。要知道,灵活和性能往往是一对矛盾,越是灵活的构架可能越复杂越庞大,如果我们不需要这种灵活性就完全没有必要使用复杂的构架来提升项目的“技术含量”。
==================
真正的数据访问层是不涉及任何数据库结构(甚至是兼容多种数据库)并提供数据的一般化操作(添加、删除、修改、查询等)的一个框架(比如ORM框架、SQLMAP框架)。
==================
能否大概讲一下.最好有一个简短的例子.谢谢你
{
AttackSpeedInfo attackspeed = new AttackSpeedInfo(reader);//此处为Model对象
//attackspeed.UserName = reader["UserName"].ToString();
//attackspeed.T = float.Parse(reader["T"].ToString());
//attackspeed.ID = reader["ID"].ToString();
AllAttackSpeed.Add(attackspeed);
}===>
看看我们这样写的时候加了什么,省略了什么
多了一个AttackSpeedInfo构造方法
省略了属性的指定
//attackspeed.UserName = reader["UserName"].ToString();
//attackspeed.T = float.Parse(reader["T"].ToString());
//attackspeed.ID = reader["ID"].ToString();所以常见的
AttackSpeedInfo(IDataReader)
应该是如下形式public AttackSpeedInfo(IDataReader reader){
UserName = reader["UserName"].ToString();
T = float.Parse(reader["T"].ToString());
ID = reader["ID"].ToString();
//...........
}同理可以实现由datarow/datarowview实现的构造
那么以后可以直接构造AttackSpeedInfo类并使用
不用关心它实现的细节,我们要的仅是AttackSpeedInfosqldatareader sda=...
while (sda.read()){
AttackSpeedInfo asi=new AttackSpeedInfo(sda)
}更进一步的方法是实现由AttackSpeedInfo自己实现sql并构造本身public AttackSpeedInfo{
public static AttackSpeedInfo getbyUserName(string name){
//实现从数据库中取得idatareader reader
//然后由datareader构造
return new AttackSpeedInfo(reader)
}
}
这样外部的调用与sql也无关了AttackSpeedInfo asi=AttackSpeedInfo .getbyUserName('我的名字')
就要以得到AttackSpeedInfo对象