Castle Active Record(Linq 和验证)问题
我正在尝试 Castle ActiveRecord。我想使用验证功能和 LINQ 功能。
为了使用 LINQ,您可以:
我的偏好:让您的实体继承自
ActiveRecordLinqBase
,然后查询:var blogs = (from b in Blog.Queryable select b).ToList();
使用
ActiveRecordLinq.AsQueryable
,例如:var blogs = (from b in ActiveRecordLinq.AsQueryable() select b).ToList()
现在,要使用验证功能,您必须使实体继承自 ActiveRecordValidationBase
。
不支持多重继承,因此,这是我的选择:
- 使用上面的#2,同时使我的实体继承自
ActiveRecordValidationBase
。缺点:LINQ 语句更长且更难看。 - 创建一个继承
ActiveRecordLinqBase
的类,并复制ActiveRecordValidationBase
中的代码。缺点:重复代码,必须使用未来的 ActiveRecord 版本进行更新。这是课程:
编辑:3.(未测试)模拟多重继承。缺点:必须使属性和方法定义与更新保持同步。
using System;
using System.Collections;
using System.Xml.Serialization;
using Castle.ActiveRecord.Framework;
using Castle.Components.Validator;
using NHibernate.Type;
namespace Castle.ActiveRecord.Linq
{
[Serializable]
public abstract class ActiveRecordValidationLinqBase<T> : ActiveRecordLinqBase<T>, IValidationProvider where T : class
{
// Fields
[NonSerialized]
private IValidationProvider _actualValidator;
// Methods
protected ActiveRecordValidationLinqBase() { }
protected override bool BeforeSave(IDictionary state)
{
if (!this.IsValid(RunWhen.Insert))
{
this.OnNotValid();
}
return base.BeforeSave(state);
}
public virtual bool IsValid()
{
return this.ActualValidator.IsValid();
}
public virtual bool IsValid(RunWhen runWhen)
{
return this.ActualValidator.IsValid(runWhen);
}
protected override bool OnFlushDirty(object id, IDictionary previousState, IDictionary currentState, IType[] types)
{
if (!this.IsValid(RunWhen.Update))
{
this.OnNotValid();
}
return base.OnFlushDirty(id, previousState, currentState, types);
}
protected virtual void OnNotValid()
{
ActiveRecordValidator.ThrowNotValidException(this.ValidationErrorMessages, this.PropertiesValidationErrorMessages);
}
// Properties
[XmlIgnore]
protected virtual IValidationProvider ActualValidator
{
get
{
if (this._actualValidator == null)
{
this._actualValidator = new ActiveRecordValidator(this);
}
return this._actualValidator;
}
}
[XmlIgnore]
public virtual IDictionary PropertiesValidationErrorMessages
{
get
{
return this.ActualValidator.PropertiesValidationErrorMessages;
}
}
public virtual string[] ValidationErrorMessages
{
get
{
return this.ActualValidator.ValidationErrorMessages;
}
}
}
}
有更好的办法吗?
I am trying out Castle ActiveRecord. I want to use the Validation features AND the LINQ features.
In order to use LINQ, you can either:
My preference: Make your entities inherit from
ActiveRecordLinqBase<T>
, then to query:var blogs = (from b in Blog.Queryable select b).ToList();
Use
ActiveRecordLinq.AsQueryable<T>
, e.g.:var blogs = (from b in ActiveRecordLinq.AsQueryable() select b).ToList()
Now, to use the validation features, you have to make your entities inherit from ActiveRecordValidationBase<T>
.
Multiple inheritance isn't supported so, here's my options:
- Use #2 from above while making my entities inherit from
ActiveRecordValidationBase<T>
. Disadvantage: LINQ statements are longer and uglier. - Create a class that inherits from
ActiveRecordLinqBase<T>
and duplicates the code found inActiveRecordValidationBase<T>
. Disadvantage: Duplicate code, which must be updated with future ActiveRecord releases. Here's the class:
Edit: 3. (Not Tested) Simulate multiple inheritance. Disadvantage: Have to keep Property and Method Definitions in sync with updates.
using System;
using System.Collections;
using System.Xml.Serialization;
using Castle.ActiveRecord.Framework;
using Castle.Components.Validator;
using NHibernate.Type;
namespace Castle.ActiveRecord.Linq
{
[Serializable]
public abstract class ActiveRecordValidationLinqBase<T> : ActiveRecordLinqBase<T>, IValidationProvider where T : class
{
// Fields
[NonSerialized]
private IValidationProvider _actualValidator;
// Methods
protected ActiveRecordValidationLinqBase() { }
protected override bool BeforeSave(IDictionary state)
{
if (!this.IsValid(RunWhen.Insert))
{
this.OnNotValid();
}
return base.BeforeSave(state);
}
public virtual bool IsValid()
{
return this.ActualValidator.IsValid();
}
public virtual bool IsValid(RunWhen runWhen)
{
return this.ActualValidator.IsValid(runWhen);
}
protected override bool OnFlushDirty(object id, IDictionary previousState, IDictionary currentState, IType[] types)
{
if (!this.IsValid(RunWhen.Update))
{
this.OnNotValid();
}
return base.OnFlushDirty(id, previousState, currentState, types);
}
protected virtual void OnNotValid()
{
ActiveRecordValidator.ThrowNotValidException(this.ValidationErrorMessages, this.PropertiesValidationErrorMessages);
}
// Properties
[XmlIgnore]
protected virtual IValidationProvider ActualValidator
{
get
{
if (this._actualValidator == null)
{
this._actualValidator = new ActiveRecordValidator(this);
}
return this._actualValidator;
}
}
[XmlIgnore]
public virtual IDictionary PropertiesValidationErrorMessages
{
get
{
return this.ActualValidator.PropertiesValidationErrorMessages;
}
}
public virtual string[] ValidationErrorMessages
{
get
{
return this.ActualValidator.ValidationErrorMessages;
}
}
}
}
Is there a better way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
未必。验证是一个单独的 Castle 项目,它与 ActiveRecord 的耦合不是很紧密。您可以手动运行验证< /a>.我所说的手动是指将其包装在您自己的存储库/DAO 类中。
由于它是松散耦合的,您甚至可以选择任何其他验证框架。
就我个人而言,我不认为
ActiveRecordLinq.AsQueryable()
比Blog.Queryable
更长或更丑,所以我会选择该选项。Not necessarily. Validation is a separate Castle project, it's not very tightly coupled to ActiveRecord. You can run the validation manually. By manually I mean wrapping this in your own repository/DAO class.
And since it's loosely coupled you could even choose any other validation framework.
Personally, I don't consider
ActiveRecordLinq<Blog>.AsQueryable()
to be much longer or uglier thanBlog.Queryable
so I'd go with that option.