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开发者_C百科 virtual string[] ValidationErrorMessages
{
get
{
return this.ActualValidator.ValidationErrorMessages;
}
}
}
}
Is there a better way?
to use the validation features, you have to make your entities inherit from ActiveRecordValidationBase.
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 than Blog.Queryable
so I'd go with that option.
精彩评论