基础实体类。 NHibernate的

时间:2011-10-31 15:35:58

标签: c# nhibernate interface entity

像这样实现实体基类是不错的做法:

[Serializable]
public abstract class Entity<T> : IComparable<Entity<T>>, IFormattable
{
    public abstract Int32 CompareTo(Entity<T> entity);
    public abstract String ToString(String format, IFormatProvider provider);

    // ...
}

因此所有派生类都必须实现这些接口。 将IComparable<T>接口放在实体类上是否合理? 谢谢!

3 个答案:

答案 0 :(得分:3)

这不是(或糟糕)的做法 - 它完全取决于您的需求。

在一般级别指定IComparable时,存在以下风险:在继承链中进一步比较某些对象可能没有意义。即使你可以比较两个对象,它总是有意义吗?您可能需要编写代码行来满足永远不会使用的合同 - 谨防YAGNI circumstances

但是,如果您需要创建绝对合约,以便可以比较从Entity继承的任何对象,那么这将没有问题。这允许您在代码中做出积极的假设。

答案 1 :(得分:2)

T会是什么?你的域名?如果是这样的话,为什么不让Entity类非泛型并直接从Entity继承?

一般来说,我发现从一个公共接口或基类派生所有可以由特定存储库处理的域类是一种很好的做法。这允许Repository对该接口是通用的,提供编译时检查,您试图使用Repository来保存Repository已映射的内容。但是,如果使用基类,则不要映射它,除非您需要一种方法来唯一标识任何实体,而不管其实际的子类类型如何;否则,您将获得该实体表(包含任何公共字段)作为数据库中的表,并且可能难以手动跟踪数据层。

然而,可能需要一个共同的映射实体;您可能希望通过公共ID列唯一地标识人员和公司,即使人员和公司被保存到不同的表中也是唯一的。

这是我在我的一个项目中使用的层次结构的消毒示例:

//identifies a class as persistable, and requires the class to specify 
//an identity column for its PK
public interface IDomainObject { long Id {get;} } 

//In a repository-per-DB model, just because it's an IDomainObject doesn't mean
//a repo can work with it. So, I derive further to create basically "marker"
//interfaces identifying domain objects as being from a particular DB:
public interface ISecurityDomainObject:IDomainObject { }
public interface IDataDomainObject:IDomainObject { }
public interface IData2DomainObject:IDomainObject { }

//There may be logic in your repo or DB to prevent certain concurrency issues.
//You can specify that a domain object has the necessary fields for version-checking
//either up at the IDomainObject level, a lower level, or independently:
public interface IVersionedDomainObject:IDomainObject
{ 
   long Version {get;}
   string LastUpdatedBy {get;}
   DateTime LastUpdatedDate {get;}
}

//Now, you can use these interfaces to restrict a Repo to a particular subset of
//the full domain, based on the DB each object is persisted to:

public interface IRepository<TDom> where TDom:IDomainObject 
{
    //yes, GTPs can be used as GTCs
    T GetById<T>(long Id) where T:TDom;
    void Save<T>(T obj) where T:TDom;

    //not only must the domain class for SaveVersioned() implement TRest,
    //it must be versionable
    void SaveVersioned<T>(T versionedObj) where T:TDom, IVersionedDomainObject
}

//and now you can close TDom to an interface which restricts the concrete
//classes that can be passed to the generic methods of the repo:

public class ISecurityRepo:IRepository<ISecurityDomainObject> { ... }

答案 2 :(得分:0)

如果您的实体需要可比性和格式而不是使用基类,这是一种非常好的做法。 有时,标识字段也在基类中实现。