I am having problems with using OptimisticLock as a Convention.
However, using OptimisticLock within Individual ClassMap's works fine. It throws Stale State Object Exceptions.
Each Class corresponding to a Table in the database has a property (which corresponds to a Column in the Table) of type DateTime which I am trying to use for Locking using OptimisticLock.Version().
It works only when I use it within every ClassMap, I don't want to write so many ClassMaps, I instead want to use Auto Mapping.
It WORKS like this within the Class Map
Version(x => x.UpdTs).Column("UPD_TS");
OptimisticLock.Version();
So, I started using Convention below, but it DOESN'T WORK.
OptimisticLock.IsAny(x => x.Version());
I tried setting the DynamicUpdate, etc. Nothing seems to work for me.
Please help !
Here's what I did to get it work using a Convention :
/// <summary>
/// Class represents the Convention which defines which Property/Column serves as a part of the Optimistic Locking Mechanism.
/// </summary>
public class VersionConvention : IVersionConvention, IVersionConventionAcceptance
{
public void Accept(IAcceptanceCriteria<IVersionInspector> criteria)
{
criteria.Expect(x => x.Name == "%COLUMN_NAME%");
}
/// <summary>
/// Method applies additional overrides to the <see cref="IVersionInstance"/>
/// </summary>
/// <param name="instance"><see cref="IVersionInstance"/></param>
public void Apply(IVersionInstance instance)
{
instance.Column("%COLUMN_NAME%");
}
}
%COLUMN_NAME% above is the Property being used for Locking using Version.
Then specified that the Version should be used for Optimistic Locking, when creating a FluentConfiguration Object, like this
OptimisticLock.Is(x => x.Version();
Related
I'm working on an application which should validate the model based on some metadata saved in a database. The purpose of this is to allow administrators change how some models are validated, without changing the code, depending on clients' preferences. The changes are applied for the entire application, not for specific users accessing it. How it is changed, doesn't matter at the moment. They could be modified directly on the database, or using an application. The idea is that they should be customizable.
Let's say i have the model "Person" with the property "Name" of type "string".
public class Person
{
public string Name { get; set; }
}
This model is used by my app which is distributed and istalled on several servers. Each of them is independent. Some users may want the Name to have maximum 30 letters and to be required when creating a new "Person", others may want it to have 25 and not to be required. Normally, this would be solved using data annotations, but those are evaluated during the compile time and are somehow "hardcoded".
Shortly, I want to find a way to customize and store in a database how the model validates, without the need of altering the application code.
Also, it would be nice to work with jquery validation and have as few request to database(/service) as possible. Besides that, i can't use any known ORM like EF.
You could create a custom validation attribute that validates by examining the metadata stored in the database. Custom validation attributes are easy to create, simply extend System.ComponentModel.DataAnnotations.ValidationAttribute and override the IsValid() method.
To get the client side rules that work with jQuery validation you will need to create a custom adapter for the type of your custom validation attribute that extends System.Web.Mvc.DataAnnotationsModelValidator<YourCustomValidationAttribute>. This class then needs to be registered in the OnApplicationStart() method of your Global.asax.
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(YourCustomValidationAttribute), typeof(YourCustomAdapter));
Here's an example adapter:
public class FooAdapter : DataAnnotationsModelValidator<FooAttribute>
{
/// <summary>
/// This constructor is used by the MVC framework to retrieve the client validation rules for the attribute
/// type associated with this adapter.
/// </summary>
/// <param name="metadata">Information about the type being validated.</param>
/// <param name="context">The ControllerContext for the controller handling the request.</param>
/// <param name="attribute">The attribute associated with this adapter.</param>
public FooAdapter(ModelMetadata metadata, ControllerContext context, FooAttribute attribute)
: base(metadata, context, attribute)
{
_metadata = metadata;
}
/// <summary>
/// Overrides the definition in System.Web.Mvc.ModelValidator to provide the client validation rules specific
/// to this type.
/// </summary>
/// <returns>The set of rules that will be used for client side validation.</returns>
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
return new[] { new ModelClientValidationRequiredRule(
String.Format("The {0} field is invalid.", _metadata.DisplayName ?? _metadata.PropertyName)) };
}
/// <summary>
/// The metadata associated with the property tagged by the validation attribute.
/// </summary>
private ModelMetadata _metadata;
}
This may also be useful if you would like to asynchronously call server side validation http://msdn.microsoft.com/en-us/library/system.web.mvc.remoteattribute(v=vs.108).aspx
If you need to Setup a return value, as well as Verify how many times the expression was called, can you do this in one statement?
From what I can gather, Moq's Setup(SomeExpression).Verifiable() called along with Verify(), basically does a Verify(SomeExpression, Times.AtLeastOnce)? i.e. it verifys the expression was called only.
Here's an example to explain the question better. For an interface:
interface IFoo
{
int ReturnSomething();
}
Are the following two blocks equivalent (other than the first will Verify all setups marked as verifiable)?
void Test()
{
var mock = new Mock<IFoo>();
mock.Setup((m) => m.ReturnSomething()).Returns(1).Verifiable();
mock.Verify();
}
and
void Test()
{
var mock = new Mock<IFoo>();
mock.Setup((m) => m.ReturnSomething()).Returns(1);
mock.Verify((m) => m.ReturnSomething(), Times.AtLeastOnce());
}
If I wanted to verify the number of calls (say twice), is this the only way, where the expression is repeated for the Setup and Verify?
void Test()
{
var mock = new Mock<IFoo>();
mock.Setup((m) => m.ReturnSomething()).Returns(1);
mock.Verify((m) => m.ReturnSomething(), Times.Exactly(2));
}
I just don't like having to call Setup and Verify. Well, since this is a good idea for AAA, to rephrase, I don't like having to repeat the expression for the Setup and Verify. At the moment I store the expression in a variable and pass it to each method, but doesn't feel so clean.
PS - The context for this is for a test checking when a cache is updated or not (expirations etc.)
I have this problem all the time. I use strict mocks, and I want to specify strictly (i.e. I used It.Is<>() instead of It.IsAny()) as well as verify strictly (i.e. specifying Times). You cannot use verifiable for this sadly, because Moq is missing a Verifiable(Times) overload.
The full expression of the call, including It.Is<>() is generally big. So in order to avoid duplication I generally resort to the following:
Expression<Action<MockedType>> expression = mockedTypeInstance => mockedTypeInstance.MockedMethod(It.Is<TFirstArgument>(firstArgument => <some complex statement>)/*, ...*/);
_mock.Setup(expression);
/* run the test*/
_mock.Verify(expression, Times.Once);
Not extremely readable, but I don't think there is another way to both use strict setup and strict verification.
To answer the first question, yes the two blocks are equivalent. Both will fail when .Verify is called if the method on the mock wasn't called.
You can't specify the verify up front as far as I am aware and if you think about it, it makes sense.
This is specifying the behavior of the mock:
mock.Setup(m => m.ReturnSomething()).Returns(1);
This is verifying the behavior of the caller:
mock.Verify(m => m.ReturnSomething(), Times.AtLeastOnce());
Personally I prefer calling verify individually to confirm the required behavior of the caller, the .Verifiable() and .Verify() are shortcuts that are less strict (they just check the method was called one or more times) however if you know your code should only call a method once, put the verify in at the end to confirm it.
I started doing that after a code merge resulted in a method being called twice, the test still passed since it was called at least once but it also meant that something else happened multiple times which shouldn't have!
Expounding on the answer by Evren Kuzucuoglu, I created the following extension methods to make creating the expressions a little simpler:
/// <summary>
/// Creates a method call expression that can be passed to both <see cref="Setup"/> and <see cref="Verify"/>.
/// </summary>
/// <typeparam name="T">Mocked object type.</typeparam>
/// <param name="mock">Mock of <see cref="T"/>.</param>
/// <param name="expression">Method call expression to record.</param>
/// <returns>Method call expression.</returns>
public static Expression<Action<T>> CallTo<T>(this Mock<T> mock, Expression<Action<T>> expression) where T : class
{
return expression;
}
/// <summary>
/// Creates a method call expression that can be passed to both <see cref="Setup"/> and <see cref="Verify"/>.
/// </summary>
/// <typeparam name="T">Mocked object type.</typeparam>
/// <typeparam name="TResult">Method call return type.</typeparam>
/// <param name="mock">Mock of <see cref="T"/>.</param>
/// <param name="expression">Method call expression to record.</param>
/// <returns>Method call expression.</returns>
public static Expression<Func<T, TResult>> CallTo<T, TResult>(this Mock<T> mock, Expression<Func<T, TResult>> expression) where T : class
{
return expression;
}
Usage example:
var createMapperCall = mockMappingFactory.CallTo(x => x.CreateMapper());
mockMappingFactory.Setup(createMapperCall).Returns(mockMapper.Object);
mockMappingFactory.Verify(createMapperCall, Times.Once());
I created a utility class that takes care of this:
public class TestUtils
{
private static List<Action> verifyActions = new List<Action>();
public static void InitVerifyActions() => verifyActions = new List<Action>();
public static void VerifyAllSetups()
{
foreach (var action in verifyActions)
{
action.Invoke();
}
}
public static ISetup<T> SetupAndVerify<T>(Mock<T> mock, Expression<Action<T>> expression, Times times) where T : class
{
verifyActions.Add(() => mock.Verify(expression, times));
return mock.Setup(expression);
}
public static ISetup<T, TResult> SetupAndVerify<T, TResult>(Mock<T> mock, Expression<Func<T, TResult>> expression, Times times) where T : class
{
verifyActions.Add(() => mock.Verify(expression, times));
return mock.Setup(expression);
}
}
Then in TestInitialize(), I call TestUtils.InitVerifyActions(), and in the unit tests:
TestUtils.SetupAndVerify(myMock, m => m.Foo("bar"), Times.Once()).Returns("baz");
TestUtils.SetupAndVerify(myOtherMock, m => m.Blah(), Times.Once());
...
TestUtils.VerifyAllSetups();
While far from enough Moq indeed has the AtMost() and AtMostOnce() methods on the Setup call, however it is marked as Obsolete, but it appears to be a mistake according to this GitHub issue
I need to use Fluent-nHibernate against a table with a composite primary key (Azure Table, primary keys being (PartitionKey,RowKey) and I would like to map them with corresponding properties on the entity (or with a component property, if easier)
my table would look like:
{
PartitionKey PK,
RowKey PK,
[..]
}
and the entity
public class MyRecord
{
public virtual string PartitionKey{get;set;}
public virtual string RowKey{get;set;}
[...]
}
My current projet uses a custom nHibernate Driver targeting AzureTable.
I managed to make it work with ClassMap or XML mappings. Therefore I am sure that the driver is working. Furthermore, the azure table HTTP requests are correct using classmaps or XML declarations.
However I really need conventions, so this isn't an acceptable solution.
Finally, there is always the option to map only RowKey as a PK, even if the Datastore use (PartitionKey,RowKey). It works too, However it's not really satisfying as it introduces an unicity handling mismatch between nHibernate and the underlying datastore.
UPDATE:
I tried to build a custom IIdentityConvention. The IIdentityInstance.Column() method takes into account only the first call.
However, if I use reflection to add both columns to the underlying mapping field, the configuration build fails with an XML validation exception (attribute 'class' required)
I got it working today, but it's not pretty. It also doesn't use a convention. As I understand conventions, they're really meant for tweaking things after the main mapping has occurred. Adding mappings I believe is considered out of scope for conventions.
In my project I have a generic automapping-based initialization procedure that knows nothing of types, but has dependency-injected mapping overrides for composite keys. Not exactly your scenario, but it's a similar problem.
The way I got this to work through reflection was to get hold of the appropriate AutoPersistenceModel object. If you have code looking like this:
Fluently.Configure().Mappings(m => ...
The AutoPersistenceModel object would be m.AutoMappings.First()
From here, it's pretty serious reflection work, culminating in a call to a protected method inside FluentNHibernate. Here's the code I'm using:
private void Override(AutoPersistenceModel container,
Type type,
IEnumerable<KeyValuePair<string,string>> compositeKeys)
{
// We need to call container.Override<T>(Action<Automapping<T>> populateMap)
// Through reflection...yikes
var overrideMethod = typeof(AutoPersistenceModel)
.GetMethod("Override")
.MakeGenericMethod(type);
var actionFactoryMethod = typeof(FluentNHibernateInitializer)
.GetMethod("CompositeMapperFactory",
BindingFlags.Instance | BindingFlags.NonPublic)
.MakeGenericMethod(type);
var actionMethod = actionFactoryMethod
.Invoke(this, new object[] { compositeKeys });
overrideMethod.Invoke(container, new object[] {actionMethod});
}
private Action<AutoMapping<T>> CompositeMapperFactory<T>
(IEnumerable<KeyValuePair<string, string>> compositeKeys)
{
return new Action<AutoMapping<T>>(m =>
{
var compositeId = m.CompositeId();
foreach (var kvp in compositeKeys)
compositeId =
AddKeyProperty(
compositeId,
typeof(T).GetProperty(kvp.Key),
kvp.Value);
}
);
}
/// <summary>
/// Uses reflection to invoke private and protected members!
/// </summary>
/// <param name="compositeId"></param>
/// <param name="propertyInfo"></param>
/// <returns></returns>
private CompositeIdentityPart<T> AddKeyProperty<T>
(CompositeIdentityPart<T> compositeId,
PropertyInfo propertyInfo,
string column)
{
var member = FluentNHibernate.MemberExtensions.ToMember(propertyInfo);
var keyPropertyMethod = typeof(CompositeIdentityPart<T>)
.GetMethod("KeyProperty",
BindingFlags.Instance | BindingFlags.NonPublic);
return (CompositeIdentityPart<T>)
keyPropertyMethod
.Invoke(compositeId, new object[] { member, column, null });
}
I have a problem with NHibernate, I can't seem to find any solution for.
In my project I have a simple entity (Batch), but whenever I try and run the following test, I get an exception.
I've triede a couple of different ways to perform a similar query, but almost identical exception for all (it differs in which LINQ method being executed).
The first test:
[Test]
public void QueryLatestBatch()
{
using (var session = SessionManager.OpenSession())
{
var batch = session.Query<Batch>()
.FirstOrDefault();
Assert.That(batch, Is.Not.Null);
}
}
The exception:
System.NullReferenceException : Object reference not set to an instance of an object.
at NHibernate.Linq.NhQueryProvider.PrepareQuery(Expression expression, ref IQuery query, ref NhLinqExpression nhQuery)
at NHibernate.Linq.NhQueryProvider.Execute(Expression expression)
at System.Linq.Queryable.FirstOrDefault(IQueryable`1 source)
The second test:
[Test]
public void QueryLatestBatch2()
{
using (var session = SessionManager.OpenSession())
{
var batch = session.Query<Batch>()
.OrderBy(x => x.Executed)
.Take(1)
.SingleOrDefault();
Assert.That(batch, Is.Not.Null);
}
}
The exception:
System.NullReferenceException : Object reference not set to an instance of an object.
at NHibernate.Linq.NhQueryProvider.PrepareQuery(Expression expression, ref IQuery query, ref NhLinqExpression nhQuery)
at NHibernate.Linq.NhQueryProvider.Execute(Expression expression)
at System.Linq.Queryable.SingleOrDefault(IQueryable`1 source)
However, this one is passing (using QueryOver<>):
[Test]
public void QueryOverLatestBatch()
{
using (var session = SessionManager.OpenSession())
{
var batch = session.QueryOver<Batch>()
.OrderBy(x => x.Executed).Asc
.Take(1)
.SingleOrDefault();
Assert.That(batch, Is.Not.Null);
Assert.That(batch.Executed, Is.LessThan(DateTime.Now));
}
}
Using the QueryOver<> API is not bad at all, but I'm just kind of baffled that the Query<> API isn't working, which is kind of sad, since the First() operation is very concise, and our developers really enjoy LINQ.
I really hope there is a solution to this, as it seems strange if these methods are failing such a simple test.
EDIT
I'm using Oracle 11g, my mappings are done with FluentNHibernate registered through Castle Windsor with the NHibernate Facility.
As I wrote, the odd thing is that the query works perfectly with the QueryOver<> API, but not through LINQ.
There is an issue with the current implementation of the LINQ extensionmethods for NHibernate 3.1.0.4000 used together with NHibernate Facility 2.0RC (and previous versions) (see: https://nhibernate.jira.com/browse/NH-2626 and discussion here: http://groups.google.com/group/castle-project-devel/browse_thread/thread/ac90148a8d4c8477)
The fix I am using at the moment is to simply ignore the LINQ extensionmethods provided by NHibernate and create it myself. They're really just one-liners:
public static class NHibernateLinqExtensions
{
/// <summary>
/// Performs a LINQ query on the specified type.
/// </summary>
/// <typeparam name="T">The type to perform the query on.</typeparam>
/// <param name="session"></param>
/// <returns>A new <see cref="IQueryable{T}"/>.</returns>
/// <remarks>This method is provided as a workaround for the current bug in the NHibernate LINQ extension methods.</remarks>
public static IQueryable<T> Linq<T>(this ISession session)
{
return new NhQueryable<T>(session.GetSessionImplementation());
}
/// <summary>
/// Performs a LINQ query on the specified type.
/// </summary>
/// <typeparam name="T">The type to perform the query on.</typeparam>
/// <param name="session"></param>
/// <returns>A new <see cref="IQueryable{T}"/>.</returns>
/// <remarks>This method is provided as a workaround for the current bug in the NHibernate LINQ extension methods.</remarks>
public static IQueryable<T> Linq<T>(this IStatelessSession session)
{
return new NhQueryable<T>(session.GetSessionImplementation());
}
}
Then, when I need to do a LINQ query, I just use session.Linq<EntityType>() instead of session.Query<EntityType>.
Hope it helps someone in the same situation that I was.
I found the following: http://groups.google.com/group/castle-project-users/browse_thread/thread/5efc9f3b7b5d6a08
Apparently there is an issue with the current version of the NHibernate Facility and NHibernate 3.1.0.4000.
I guess I'll just have to wait for a fix :)
I've just discovered that if I get an object from an NHibernate session and change a property on object, NHibernate will automatically update the object on commit without me calling Session.Update(myObj)!
I can see how this could be helpful, but as default behaviour it seems crazy!
Update: I now understand persistence ignorance, so this behaviour is now clearly the preferred option. I'll leave this now embarrassing question here to hopefully help other profane users.
How can I stop this happening? Is this default NHibernate behaviour or something coming from Fluent NHibernate's AutoPersistenceModel?
If there's no way to stop this, what do I do? Unless I'm missing the point this behaviour seems to create a right mess.
I'm using NHibernate 2.0.1.4 and a Fluent NHibernate build from 18/3/2009
Is this guy right with his answer?
I've also read that overriding an Event Listener could be a solution to this. However, IDirtyCheckEventListener.OnDirtyCheck isn't called in this situation. Does anyone know which listener I need to override?
You can set Session.FlushMode to FlushMode.Never. This will make your operations explicit
ie: on tx.Commit() or session.Flush(). Of course this will still update the database upon commit/flush. If you do not want this behavior, then call session.Evict(yourObj) and it will then become transient and NHibernate will not issue any db commands for it.
Response to your edit: Yes, that guy gives you more options on how to control it.
My solution:
In your initial ISession creation, (somewhere inside your injection framework registrations) set DefaultReadOnly to true.
In your IRepository implementation which wraps around NHibernate and manages the ISession and such, in the Insert, Update, InsertUpdate and Delete (or similar) methods which call ISession.Save, Update, SaveUpdate, etc., call SetReadOnly for the entity and flag set to false.
Calling SaveOrUpdate() or Save() makes an object persistent. If you've retrieved it using an ISession or from a reference to a persistent object, then the object is persistent and flushing the session will save changes. You can prevent this behavior by calling Evict() on the object which makes it transient.
Edited to add: I generally consider an ISession to be a unit of work. This is easily implemented in a web app. using session-per-request but requires more control in WinForms.
We did this by using the Event Listeners with NH (This isn't my work - but I can't find the link for where I did it...).
We have a EventListener for when reading in the data, to set it as ReadOnly - and then one for Save (and SaveOrUpdate) to set them as loaded, so that object will persist when we manually call Save() on it.
That - or you could use an IStatelessSession which has no State/ChangeTracking.
This sets the entity/item as ReadOnly immediately on loading.
I've only included one Insertion event listener, but my config code references all of them.
/// <summary>
/// A listener that once an object is loaded will change it's status to ReadOnly so that
/// it will not be automatically saved by NH
/// </summary>
/// <remarks>
/// For this object to then be saved, the SaveUpdateEventListener is to be used.
/// </remarks>
public class PostLoadEventListener : IPostLoadEventListener
{
public void OnPostLoad(PostLoadEvent #event)
{
EntityEntry entry = #event.Session.PersistenceContext.GetEntry(#event.Entity);
entry.BackSetStatus(Status.ReadOnly);
}
}
On saving the object, we call this to set that object to Loaded (meaning it will now persist)
public class SaveUpdateEventListener : ISaveOrUpdateEventListener
{
public static readonly CascadingAction ResetReadOnly = new ResetReadOnlyCascadeAction();
/// <summary>
/// Changes the status of any loaded item to ReadOnly.
/// </summary>
/// <remarks>
/// Changes the status of all loaded entities, so that NH will no longer TrackChanges on them.
/// </remarks>
public void OnSaveOrUpdate(SaveOrUpdateEvent #event)
{
var session = #event.Session;
EntityEntry entry = session.PersistenceContext.GetEntry(#event.Entity);
if (entry != null && entry.Persister.IsMutable && entry.Status == Status.ReadOnly)
{
entry.BackSetStatus(Status.Loaded);
CascadeOnUpdate(#event, entry.Persister, #event.Entry);
}
}
private static void CascadeOnUpdate(SaveOrUpdateEvent #event, IEntityPersister entityPersister,
object entityEntry)
{
IEventSource source = #event.Session;
source.PersistenceContext.IncrementCascadeLevel();
try
{
new Cascade(ResetReadOnly, CascadePoint.BeforeFlush, source).CascadeOn(entityPersister, entityEntry);
}
finally
{
source.PersistenceContext.DecrementCascadeLevel();
}
}
}
And we implement it into NH thus so:
public static ISessionFactory CreateSessionFactory(IPersistenceConfigurer dbConfig, Action<MappingConfiguration> mappingConfig, bool enabledChangeTracking,bool enabledAuditing, int queryTimeout)
{
return Fluently.Configure()
.Database(dbConfig)
.Mappings(mappingConfig)
.Mappings(x => x.FluentMappings.AddFromAssemblyOf<__AuditEntity>())
.ExposeConfiguration(x => Configure(x, enabledChangeTracking, enabledAuditing,queryTimeout))
.BuildSessionFactory();
}
/// <summary>
/// Configures the specified config.
/// </summary>
/// <param name="config">The config.</param>
/// <param name="enableChangeTracking">if set to <c>true</c> [enable change tracking].</param>
/// <param name="queryTimeOut">The query time out in minutes.</param>
private static void Configure(NHibernate.Cfg.Configuration config, bool enableChangeTracking, bool enableAuditing, int queryTimeOut)
{
config.SetProperty(NHibernate.Cfg.Environment.Hbm2ddlKeyWords, "none");
if (queryTimeOut > 0)
{
config.SetProperty("command_timeout", (TimeSpan.FromMinutes(queryTimeOut).TotalSeconds).ToString());
}
if (!enableChangeTracking)
{
config.AppendListeners(NHibernate.Event.ListenerType.PostLoad, new[] { new Enact.Core.DB.NHib.Listeners.PostLoadEventListener() });
config.AppendListeners(NHibernate.Event.ListenerType.SaveUpdate, new[] { new Enact.Core.DB.NHib.Listeners.SaveUpdateEventListener() });
config.AppendListeners(NHibernate.Event.ListenerType.PostUpdate, new[] { new Enact.Core.DB.NHib.Listeners.PostUpdateEventListener() });
config.AppendListeners(NHibernate.Event.ListenerType.PostInsert, new[] { new Enact.Core.DB.NHib.Listeners.PostInsertEventListener() });
}
}