如何处理三层结构中的多对多关系?
数据库中的两个实体是用户-车辆,他们是多对多的关系。
于是有三个表来表示
用户表->用户车辆关系表<-车辆表
同样的,在model层里面定义了三个类
class User
class UserVehicle
class Vehicle
---------------------------------------------------
问题有两个
1.我要查一个用户对应的车辆信息
我是直接在User类的属性里面包含一个IList<Vehicle>好呢还是通过UserVehicle这个类来传递好呢?
1).用前一种方法,假设数据库的表和程序名字一样
sql语句可能是:
select ... from UserVehicle a left join Vehicle b on a.VehicleID = b.VehicleID where a.UserID = @userID
数据访问层就是
public IList<Vehicle> GetVehicleByUserID(string userID)
这样在逻辑层直接调用就可以了
2).用后一种方法就是User类里没有这个属性,在UserVehicle里面有个方法是
IList<UserVehicle> GetUserVehicleByUserID(string userID)
用这个方法得到的UserVehicle集合的VehicleID再到IVehicle里面取Vehicle信息
Vehicle类里面有这个方法
Vehicle GetVehicleByVehicleID(string vehicleID)
这种方法只能到逻辑层去构建一个函数了,也就相当于在逻辑层的一个UserBusiness类里面有个
public IList<Vehicle> GetVehicleByUserID(string userID),在这个函数里进行一系列的操作.
第一种方法感觉对应关系表没有多少意义了,第二种方法又感觉效率太低下,如果用户对应的车多,就得查N次。问问大伙都是怎么来处理这种
情况的?
2.多对多关系中,我建立了在UserVehicle表上外键约束,User表删除一个ID或者Vehicle表删除一个ID在UserVehicle中就自动删除了,这样我
在程序里面就不必自己来删除了,但是给一个用户分配车辆的时候就需要自己来增加UserVehicle中的数据,我的问题是:
1).程序里面只有添加,没有删除,这样是否妥当?
2).我是在数据访问层的User类中增加这个功能呢,还是到逻辑层的时候构建一个UserBusiness再来实现这个功能?
------解决方案--------------------1.
不应有 class UserVehicle 的存在
2.
”理想“的设计也许是
<<<place holder>>>
3.
LZ所列问题,我想都是困恼OO新手的常见问题,实际上这些都是 Object- Relation 之间不可逾越的鸿沟所造成
按大师的理想设计,舒服的 OO,只有通过 O/R mapping 工具如 Nhibernate, Unit,ActiveRecord 才能完成,
其中需要注意的是 lazy-load
自己实现“完美” Persistence Layer 是一项可怕的工作量,进度控制下,符合自己的需求即可!
------解决方案--------------------以下是基本股价,看起来是够 elegant,但可想而已手工编码的工作量,
而且,我略去了许多额外逻辑控制....
// Model
class User
{
public int ID
{
get;
set;
}
public VehicleCollection Vehicles // 集合类型通常不公开 setter
{
get;
}
}
class UserCollection : Collection<User>
{
}
class Vehicle
{
}
class UserCollection : Collection<User>
{
public UserCollection Users // 集合类型通常不公开 setter
{
get;
}
}
// BLL
public VehicleCollection GetVehiclesOfUser(string userId)
{
User user = new User(userId);
return GetVehiclesOfUser(user);
}
public VehicleCollection GetVehiclesOfUser(User user)
{
return DAL.FillVehicles(user);
}
// DAL
public VehicleCollection FillVehicles(User user)
{
//...
DbCommand.Parameters.Add("@UserID", user.ID);
// ...
using(DataReader){
while(DataReader.Read()){
Vehicle v = new Vehicle();
v.ID = (int)dr["VehicleID"];
//...
user.Vehicles.Add(v);
}
}
}