C# 软删除存储库,同时保持属性私有
我有一套基于实体框架(EntityFramework,EF)的存储库,其中一些存储库处理可以软删除的实体(并非所有存储库都可以)。实体由EF自动生成。到目前为止,我已经:C# 软删除存储库,同时保持属性私有,c#,entity-framework,oop,repository,C#,Entity Framework,Oop,Repository,我有一套基于实体框架(EntityFramework,EF)的存储库,其中一些存储库处理可以软删除的实体(并非所有存储库都可以)。实体由EF自动生成。到目前为止,我已经: 可软删除的实体实现ICanBeSoftDeleted接口: public interface ICanBeSoftDeleted { bool IsDeleted { get; set; } } 对于这些实体,我使用实现ISoftDeleteRepository的存储库: public interface ISo
- 可软删除的实体实现ICanBeSoftDeleted接口:
public interface ICanBeSoftDeleted { bool IsDeleted { get; set; } }
- 对于这些实体,我使用实现ISoftDeleteRepository的存储库:
public interface ISoftDeleteRepository<T> : IRepository<T> where T : class, ICanBeSoftDeleted { void SoftDelete(T entity); void SoftDelete(Expression<Func<T, bool>> where); }
然而,这对我来说就像是一个补丁,我不认为它解决了更大的设计问题…你必须将EF类隐藏在墙后面,并映射到POCO;或者在将它们传递给使用者时,将它们作为接口(不声明setter)键入 第二个选项使对象保持打开状态,以便通过反射设置“已删除”标志 编辑:对您发布的代码的进一步分析会导致以下问题: 您是否打算让API的使用者能够声明存储库 在API中只公开非通用存储库(例如CustomerRepository、UserRepository、PurchaseRepository)似乎更明智 然后,非泛型API形成一个干净的边界,您可以从中为API使用者将EF类与POCO分离
编辑: 这里我描述了一个属性的创建,该属性可用于检测是否从有效位置调用了属性或功能public bool IsDeleted { get { return this.isDeleted; } //you can use protected if you intend to inherit the property and override it private set { this.isDeleted= value; } }
- 在类中需要一个受保护的变量,以便验证IsDeleted属性。为了简单起见,我们假设它是一个字符串,并将其称为softDeleteKey
- 这个变量需要一个公共setter,现在我们称它为setSoftDeleteKey
- 您需要一个私有函数来检查密钥的有效性,如果有效则返回true,如果无效则返回false。我们称之为validateSoftDeleteKey
- 实现一个名为isSoftDeleteKeyValid的只读属性,该属性将调用3中描述的函数
- 在IsDeleted属性中,检查isSoftDeleteKeyValid。如果返回false,则抛出异常。如果IsDeleted成功,请将softDeleteKey设置为无效值
- 在SoftDelete方法中,在设置IsDeleted属性之前,使用有效值调用setSoftDeleteKey。如果发生异常,则使用无效值调用setSoftDeleteKey
我希望这些想法能对您有所帮助。您可以通过检查实体是否是在您的存储库中删除的ICanBeSoftDeleted的实现来实现吗 使用此处的扩展名:
公共静态类类型扩展
{
//http://bradhe.wordpress.com/2010/07/27/how-to-tell-if-a-type-implements-an-interface-in-net/
公共静态bool是的实现(此类型为baseType,类型为interfaceType)
{
返回baseType.GetInterfaces().Any(interfaceType.Equals);
}
}
公共接口假定
{
无效删除(T实体);
}
公共类RepositoryBase:IRepository,其中T:class
{
公共作废删除(T实体)
{
if(typeof(T).i实现(typeof(icanbesofteded)))
{
((ICanBeSoftDeleted)实体)。IsDeleted=true;
//等
}
其他的
{
//硬删除
}
}
}
公共类客户:已删除
{
公共布尔被删除{get;set;}
}
公共类UOW
{
私有IRepository GetRepository()
{
返回(IRepository)新的RepositoryBase();
}
公共电子储蓄客户储蓄
{
得到
{
返回GetRepository();
}
}
}
公共接口已删除
{
布尔被删除{get;set;}
}
这个怎么样:
public interface ICanBeSoftDeleted
{
bool IsDeleted { get; }
}
public abstract class CanBeSoftDeleted : ICanBeSoftDeleted
{
private bool _IsDeleted;
public bool IsDeleted
{
get { return _IsDeleted; }
}
internal void SetIsDeleted(bool value) { _IsDeleted = value; }
}
然后模型可以从抽象类继承,而不是其思想是只公开非泛型存储库。问题是,如果ICCustomerRepository是公共的,那么它扩展的抽象类RepositoryBase也需要是公共的。这将允许人们自己创建扩展RepositoryBase的存储库,我不希望。。。有什么想法吗?我想使用EF生成的POCO作为DTO,所以我不会选择第一个选项。我考虑了第二种方法,从ICanBeSoftDeleted接口中删除“set”,并在存储库中设置反射。然而,这似乎有点“黑客”对我来说。。。是否存在任何性能问题?这不会阻止使用者使用与您相同的技术来摆弄已删除的标志。将setter设置为私有或受保护可防止我在SoftDelete()中修改其值然后您可以创建一个bool属性,当且仅当设置IsDeleted是一个有效操作时,该属性才为true。在IsDeleted属性中,忘记受保护的关键字,如果从无效位置调用setter,则在setter中抛出和异常。实现InvalidReferenceToIsDeleteSetterException并抛出该异常…我如何才能做到这一点?该方法将由引用它的外部工具从程序集内部和外部调用。你能展示一些示例代码吗?@chuwik,我已经用上一条消息中提到的bool属性的描述编辑了我的答案。谢谢编辑!然而,在这种情况下,反射看起来仍然是一个更干净的解决方案。可以软删除的实体也可以硬删除。硬删除方法在RepositoryBase上,而软删除方法仅在SoftRepositoryBase上添加,因此只有那些实体才能使用它。不幸的是,我们不能使用这种方法,所以用户可以调用SoftDelete(),将IsDeleted设置为true(并调用Update),但您不想让他们直接将isdelete设置为true。这是因为您担心他们可能会忘记调用Update()?不,这是因为软删除某些内容不仅仅如此;我简化了示例的方法,但我也希望始终记录活动,may
public bool IsDeleted
{
get
{
return this.isDeleted;
}
//you can use protected if you intend to inherit the property and override it
private set
{
this.isDeleted= value;
}
}
public static class TypeExtensions
{
//http://bradhe.wordpress.com/2010/07/27/how-to-tell-if-a-type-implements-an-interface-in-net/
public static bool IsImplementationOf(this Type baseType, Type interfaceType)
{
return baseType.GetInterfaces().Any(interfaceType.Equals);
}
}
public interface IRepository<T>
{
void Delete(T entity);
}
public class RepositoryBase<T> : IRepository<T> where T : class
{
public void Delete(T entity)
{
if (typeof(T).IsImplementationOf(typeof(ICanBeSoftDeleted)))
{
((ICanBeSoftDeleted)entity).IsDeleted = true;
//etc
}
else
{
//hard delete
}
}
}
public class Customer : ICanBeSoftDeleted
{
public bool IsDeleted { get; set; }
}
public class UOW
{
private IRepository<T> GetRepository<T>()
{
return (IRepository<T>)new RepositoryBase<T>();
}
public IRepository<Customer> CustomerRepository
{
get
{
return GetRepository<Customer>();
}
}
}
public interface ICanBeSoftDeleted
{
bool IsDeleted { get; set; }
}
public interface ICanBeSoftDeleted
{
bool IsDeleted { get; }
}
public abstract class CanBeSoftDeleted : ICanBeSoftDeleted
{
private bool _IsDeleted;
public bool IsDeleted
{
get { return _IsDeleted; }
}
internal void SetIsDeleted(bool value) { _IsDeleted = value; }
}