使用将用于抽象DAL操作的接口在BL上实现CRUD的最佳方法是什么?我需要你的意见..
这是我的草稿..
数据库表中映射的数据实体
public class Student
{
public string StudentId { get; set; }
public string StudentName { get; set; }
public Course StudentCourse { get; set; }
}
public class Course
{
public string CourseCode { get; set; }
public string CourseDesc { get; set; }
}
我创建了一个CRUD接口来抽象对象的操作
public interface IMaintanable<T>
{
void Create(T obj);
T Retrieve(string key);
void Update(string key);
void Delete(string key);
}
然后是通过实现接口
来管理实体及其操作的组件public class StudentManager : IMaintainable<Student>
{
public void Create(Student obj)
{
// inserts record in the DB via DAL
}
public Student Retrieve(string userId)
{
// retrieveds record from the DB via DAL
}
public void Update()
{
// should update the record in the DB
}
public void Delete(string userId)
{
// deletes record from the DB
}
}
样本用法
public void Button_SaveStudent(Event args, object sender)
{
Student student = new Student()
{
StudentId = "1", StudentName = "Cnillincy"
}
new StudentManager().Create(student);
}
如您所见,更新方法存在相当大的异常
public void Update()
{
// should update the record in the DB
}
此方法应该更新对象属性?我应该继承学生吗?
public class StudentManager : Student , IMaintainable<Student>
{
public void Update()
{
//update record via DAL
}
}
public void Button_SaveStudent(Event args, object sender)
{
Student student = new StudentManager();
student.StudentId = "1";
student.StudentName = "Cnillincy"
student.Update()
}
或者我应该只将Student课程作为学生管理员的属性包含在内?
public class StudentManager : IMaintainable<Student>
{
public Student student { get; private set };
public void Create() {}
public void Update() {}
public void Retrieve() {}
public void Delete() {}
}
哪个更合适?接口怎么样?还有其他建议吗? thanks..C
答案 0 :(得分:15)
您的CRUD界面应该看起来像
public interface IMaintanable<T>
{
string Create(T obj);
T Retrieve(string key);
void Update(T obj);
void Delete(string key);
}
即,Create
和Update
都会获取您正在更新的对象的副本。区别在于Update
可以从key
获取obj
,因此它知道它正在改变哪个对象。 Create
通常会导致创建密钥,因此您将其作为返回值传回。希望有所帮助。
(更新也可能会传回密钥。)
答案 1 :(得分:9)
就我个人而言,我认为你所缺少的只是适当的术语。这实际上是一个非常有用的模式的近似,称为存储库模式。就类型感知而言,实现将被称为通用存储库。
我过去亲自实现的方式是拥有一个定义存储库的接口,例如IRepository<T>
,以及一个特定于存储库类型的基类,例如SqlRepositoryBase<T>
。我这样做的原因是我可以将特定于实现的代码放在基类中。因此,管道已经完成,我可以担心最终存储库中的特定于域的实现,如StudentRepository
,SqlRepository<Student>
(或SqlRepository<IStudent
&gt;实体)。
似乎你担心有多少对象被实现,我可以告诉你,你并没有产生足够的资源消耗来真正关注以这种方式实现。老人可能会对这个事实感到畏缩,但我们不再试图优化64k或RAM了。 ;-)更多关于可维护性,代码合同等。
不要预先添加不必要的复杂性,但如果您正在寻找将不同类型的多个实体列入原子事务中,您也可能需要查看工作单元模式。
以下是这些主题的几个很好的参考资料:
总的来说(IMHO)有两个要点:
我个人不同意存储库模式方法仅在大型项目中有用的假设;特别是Generic Repository模式。如果你开始将这样的代码放入一个可重用的库中,你会惊讶于你能够多快地开始创建一个宝贵的构建块资源。
这种方法的最大优点是它的可测性;甚至比可重用性更重要。如果您希望模拟您的存储库以获得任何类型的TDD方法,您可以轻松地完成此操作。这将允许您在整个代码中围绕存储库的用法编写更丰富的测试。
答案 2 :(得分:3)
我从Rob Conery那里看到了我真正喜欢的东西。它的强大之处在于您可以传递给方法的参数的灵活性。你的建议不够强大IMO。在这里查看他的MVC入门套件http://mvcstarter.codeplex.com/(在那里称为ISession)。
public interface IMaintainable : IDisposable
{
T Single<T>(Expression<Func<T, bool>> expression) where T : class, new();
System.Linq.IQueryable<T> All<T>() where T : class, new();
void Add<T>(T item) where T : class, new();
void Update<T>(T item) where T : class, new();
void Delete<T>(T item) where T : class, new();
void Delete<T>(Expression<Func<T, bool>> expression) where T : class, new();
void DeleteAll<T>() where T : class, IEntity, new();
void CommitChanges();
}
答案 3 :(得分:1)
我不会让StudentManager继承Student,我会像我的create方法一样使Update方法无状态,即
public interface IMaintanable<T>
{
void Create(T obj);
T Retrieve(string key);
void Update(T obj);
void Delete(string key);
}
和
public void Update(T obj)
{
// should update the record in the DB
}
答案 4 :(得分:0)
查看最近发布的新Entity Framework 4。它们具有“按惯例代码”模型,允许您轻松地将业务对象直接映射到数据库,而无需担心DAL。
“Gu”有一个great series概述了映射对象的容易程度,甚至在通过它使用的DbContext模型链接到数据库时进行一些简单的修改。
值得注意的是,当前版本是在CTP4,但我预计大部分问题已经在框架中得到解决,并且应该为您提供良好的服务。
答案 5 :(得分:0)
我在这里稍微改变了一下回答:
public interface IMaintanable<T>
{
Guid Create(T obj);
T Read(Guid key);
bool Update(T obj);
bool Delete(Guid key);
}
此界面基于我的数据库结构。我使用Guids作为主键。