也許我提出以下建議,這是我用我自己的EF支持的項目:
我有一個Address
類從另一個類繼承Int32Entity
。 Int32Entity
繼承於另一個類Entity
並實現兩個接口:ICreatableEntity_TKey
;和IIndexableEntity_TKey
。最後,Entity
類還實現了兩個其他接口:ICreatableEntity
;和IRemovableEntity
。所以,令人困惑的是,這裏是在正確的順序代碼:
ICreatableEntity和ICreatableEntity_TKey接口
public interface ICreatableEntity {
Employee CreatedBy { get; set; }
DateTime CreatedDateTime { get; set; }
}
public interface ICreatableEntity<TKey> :
ICreatableEntity {
TKey CreatedById { get; set; }
}
IIndexableEntity_TKey接口
public interface IIndexableEntity<TKey>
where TKey : struct {
TKey Id { get; set; }
}
IRemovableEntity接口
public interface IRemovableEntity {
bool IsRemoved { get; set; }
int? RemovedById { get; set; }
DateTime? RemovedDateTime { get; set; }
Employee RemovedBy { get; set; }
}
實體類
public class Entity :
ICreatableEntity,
IRemovableEntity {
#region ICreatableEntity Members
public DateTime CreatedDateTime { get; set; }
public virtual Employee CreatedBy { get; set; }
#endregion
#region IRemovableEntity Members
public bool IsRemoved { get; set; }
public int? RemovedById { get; set; }
public DateTime? RemovedDateTime { get; set; }
public virtual Employee RemovedBy { get; set; }
#endregion
public Entity() {
this.CreatedDateTime = DateTime.Now;
}
}
Int32Entity類
public class Int32Entity :
Entity,
ICreatableEntity<int>,
IIndexableEntity<int> {
#region ICreatableEntity`TKey Members
public int CreatedById { get; set; }
#endregion
#region IIndexableEntity Members
public int Id { get; set; }
#endregion
}
最後,但並非最不重要的地址類(省略了一些項目特定的代碼)
public class Address : Int32Entity {
public string Street { get; set; }
public string City { get; set; }
public int Zip { get; set; }
public string Building { get; set; }
public string Unit { get; set; }
public UnitType? UnitType { get; set; }
public string CrossStreets { get; set; }
public int? GateCode { get; set; }
public AddressType Type { get; set; }
public DbGeography Position { get; set; }
#region Relationship Properties
public byte StateId { get; set; }
public virtual State State { get; set; }
#endregion
}
還有byte
和short
及其可空的等價物Int32Entity
類。雖然它看起來可能有很多的繼承,但它起作用,而且效果很好。這些接口基本上保證了繼承對象將具有描述何時被創建或刪除以及由誰來描述的屬性。多個被竊等級也是將事情分開的必要條件,因爲我確實有一些不像其他實體那樣行爲的實體,比如那些具有複合關鍵字的實體。
此外,接口然後可以在您的項目層次結構用作泛型約束別的地方如果需要的話,我在我的DbContext
實施做了這裏:Entity Framework 6.1 - SaveChanges fails with Optional Principal relationship(答案)。
最後,一對夫婦的批評筆記:
- 你使用太多字符串爲您的屬性。
State
和Country
屬性應分解爲單個的State
和Country
對象,然後將其與您的Address
對象關聯。請參閱下面的示例。
Line1
,Line2
和Line3
屬性對於除您之外的任何人都絕對沒有任何意義。雖然它通常用於整個Interworld的形式,但我個人認爲它很sl。。請注意,在我的Address
課程中,我試圖獲得非常詳細的內容,所以我知道什麼是什麼,然後我可以轉向並格式化數據以便按需顯示。
- 沒有必要爲一個對象創建一個
IAddress
接口。接口是爲了在多個對象中使用,而你並沒有這樣做。如果你繼續沿着這條道路前進,那麼最終可能會有Email : IEmail
,Phone : IPhone
等等,這些都是毫無意義的。
- 您正在使用
virtual
關鍵字太多。 virtual
用於延遲加載相關的實體,而不是對象的屬性。您永遠不會延遲加載City
,State
,PostalCode
或Country
屬性,這些屬性在地址上彼此獨立,因爲那樣它就不再是一個完整且有用的地址。
忽略這一行,試圖欺騙,使文本格式...
public class State {
// If you need more than 256 State entities, just bump it to a short
// and you should be good to for every possible State (or Province) in the world
public byte Id { get; set; }
public string Abbreviation { get; set; }
public string Name { get; set; }
}
public class Country {
public byte Id { get; set; }
public string Abberviation { get; set; }
public string Name { get; set; }
}
public class Address {
// Blah, blah, blah...
// Nullable because not all countries have states
public byte? StateId { get; set; }
public byte CountryId { get; set; }
public virtual State { get; set; }
public virtual Country { get; set; }
}
我希望這可以幫助你。
1)爲什麼'EntityBase'的泛型參數? 2)接口支持多重繼承3)您是否考慮過在這裏使用組合而不是繼承? – CodesInChaos
@CodesInChaos - 所以我可以使用該類型作爲約束來確保它是一個類。 – Sam
@CodesInChaos - '您是否考慮過在這裏使用組合而不是繼承?'您能否在這段代碼的上下文中提供一個快速示例? – Sam