I read and implemented Trying to using Nhibernate with Mono & SQLite - can't find System.Data.SQLite
However, as the last comment there states this seems not to work with NHibernate 3.1
The error is
HibernateException: The IDbCommand and IDbConnection implementation in
the assembly Mono.Data.Sqlite could not be found. Ensure that the
assembly Mono.Data.Sqlite is [...reachable...]
I have Mono.Data.Sqlite in the GAC.
I have tried both specifying "Mono.Data.Sqlite" as well as typeof(Mono.Data.Sqlite.SqliteConnection).Assembly.FullName as the name of the assembly
Has anyone any Ideas how to get this working?
There is a problem in the answer of Trying to using Nhibernate with Mono & SQLite - can't find System.Data.SQLite .
For the given constructor (3 parameters) to work the assembly in question (Mono.Data.Sqlite) needs to be loaded first.
This works if the 4-parameter base contructor is used like this:
public class MonoSQLiteDriver : NHibernate.Driver.ReflectionBasedDriver
{
public MonoSQLiteDriver()
: base(
"Mono.Data.Sqlite",
"Mono.Data.Sqlite",
"Mono.Data.Sqlite.SqliteConnection",
"Mono.Data.Sqlite.SqliteCommand")
{
}
public override bool UseNamedPrefixInParameter {
get {
return true;
}
}
public override bool UseNamedPrefixInSql {
get {
return true;
}
}
public override string NamedPrefix {
get {
return "#";
}
}
public override bool SupportsMultipleOpenReaders {
get {
return false;
}
}
}
(Still, credit goes to http://intellect.dk/post/Why-I-love-frameworks-with-lots-of-extension-points.aspx for the original idea - thanks.)
And if you use FluentNHibernate, then you'll also need:
public class MonoSQLiteConfiguration : PersistenceConfiguration<MonoSQLiteConfiguration>
{
public static MonoSQLiteConfiguration Standard
{
get { return new MonoSQLiteConfiguration(); }
}
public MonoSQLiteConfiguration()
{
Driver<MonoSQLiteDriver>();
Dialect<SQLiteDialect>();
Raw("query.substitutions", "true=1;false=0");
}
public MonoSQLiteConfiguration InMemory()
{
Raw("connection.release_mode", "on_close");
return ConnectionString(c => c
.Is("Data Source=:memory:;Version=3;New=True;"));
}
public MonoSQLiteConfiguration UsingFile(string fileName)
{
return ConnectionString(c => c
.Is(string.Format("Data Source={0};Version=3;New=True;", fileName)));
}
public MonoSQLiteConfiguration UsingFileWithPassword(string fileName, string password)
{
return ConnectionString(c => c
.Is(string.Format("Data Source={0};Version=3;New=True;Password={1};", fileName, password)));
}
}
I have not encountered any problems so far...
Related
I have a class with a collection that needs validation. The generic on the collection takes an interface and different types can be added to the collection.
What is the cleanest path forward to creating a FluentValidation validator that supports polymorphism?
public interface IWizardStep {}
public class WizardOne : IWizardStep
{
public string Model { get; set; }
}
public class WizardTwo : IWizardStep
{
public string FirstName { get; set; }
}
public class Wizard
{
public Wizard()
{
var w1 = new WizardOne();
var w2 = new WizardTwo();
Steps = new List<IWizardStep>
{
w1,
w2
};
}
public IList<IWizardStep> Steps { get; set; }
}
public class WizardValidator : AbstractValidator<Wizard>
{
public WizardValidator()
{
RuleFor(x => x.Steps)
// Steps First where is WizardOne
// Model.NotEmpty()
// Steps First where is WizardTwo
// FirstName.NotEmpty()
}
FluentValidation doesn't support polymorphism for child collections like this out of the box, but you can add this behaviour by using a custom property validator, or by using OfType in your rule definitions.
I've written about both approaches before here:
Step 1: Create a validator for each implementor
Start by creating a validator for WizardOne and WizardTwo:
public class WizardOneValidator : AbstractValidator<WizardOne> {
public WizardOneValidator() {
RuleFor(x => x.Model).NotEmpty();
}
}
public class WizardTwoValidator : AbstractValidator<WizardTwo> {
public WizardTwoValidator() {
RuleFor(x => x.FirstName).NotEmpty();
}
}
Step 2: Create the parent validator
You have two options for defining the parent validator. The simplest approach is to use OfType, but this is less performant. The more complex option is to use a custom property validator.
Option 1: Using OfType
public WizardValidator : AbstractValidator<Wizard> {
public WizardValidator() {
RuleForEach(x => x.Steps.OfType<WizardOne>()).SetValidator(new WizardOneValidator());
RuleForEach(x => x.Steps.OfType<WizardTwo>()).SetValidator(new WizardTwoValidator());
}
}
This is the simplest approach, but calling OfType inside the call RuleFor will end up bypassing FluentValidation's expression cache, which is a potential performance hit. It also iterates the collection multiple. This may or may not be an issue for you - you'll need to decide if this has any real-world impact on your application.
Option 2: Using a custom PropertyValidator.
This uses a custom custom validator which can differentiate the underlying type at runtime:
public WizardValidator : AbstractValidator<Wizard> {
public WizardValidator() {
RuleForEach(x => x.Steps).SetValidator(new PolymorphicValidator<Wizard, IWizardStep>()
.Add<WizardOne>(new WizardOneValidator())
.Add<WizardTwo>(new WizardTwoValidator())
);
}
}
Syntactically, this isn't quite as nice, but doesn't bypass the expression cache and doesn't iterate the collection multiple times. This is the code for the PolymorphicValidator:
public class PolymorphicValidator<T, TInterface> : ChildValidatorAdaptor<T, TInterface> {
readonly Dictionary<Type, IValidator> _derivedValidators = new Dictionary<Type, IValidator>();
// Need the base constructor call, even though we're just passing null.
public PolymorphicValidator() : base((IValidator<TInterface>)null, typeof(IValidator<TInterface>)) {
}
public PolymorphicValidator<T, TInterface> Add<TDerived>(IValidator<TDerived> derivedValidator) where TDerived : TInterface {
_derivedValidators[typeof(TDerived)] = derivedValidator;
return this;
}
public override IValidator<TInterface> GetValidator(PropertyValidatorContext context) {
// bail out if the current item is null
if (context.PropertyValue == null) return null;
if (_derivedValidators.TryGetValue(context.PropertyValue.GetType(), out var derivedValidator)) {
return new ValidatorWrapper(derivedValidator);
}
return null;
}
private class ValidatorWrapper : AbstractValidator<TInterface> {
private IValidator _innerValidator;
public ValidatorWrapper(IValidator innerValidator) {
_innerValidator = innerValidator;
}
public override ValidationResult Validate(ValidationContext<TInterface> context) {
return _innerValidator.Validate(context);
}
public override Task<ValidationResult> ValidateAsync(ValidationContext<TInterface> context, CancellationToken cancellation = new CancellationToken()) {
return _innerValidator.ValidateAsync(context, cancellation);
}
public override IValidatorDescriptor CreateDescriptor() {
return _innerValidator.CreateDescriptor();
}
}
}
This will probably be implemented in the library as a first class feature at some point in the future - you can track its development here if you're interested.
In experimenting with Service Fabric remoting I have some data types that are not serialized correctly. This is causing me many issues.
From the documentation it appears that everything needs to be decorated with [DataContract]. After using this on some test types it does appear that they serialize correctly.
However I frankly don't want to have to decorate everything. That would be a huge step backwards for me. I would prefer to use custom serialization all the way around.
This documentation seems to suggest that it is possible to register a custom serializer however it appears to only be for stateful services. I am primarily using remoting with stateless services.
The current remoting stack requires that your types use DataContract. Supposedly the team is close to releasing a new remoting stack in the near future that contains the ability to plug in custom serialization and a lot of improvements on the performance side but this is not available yet.
In the meantime, a workaround (not a very nice one mind you) is to make all of your proxies receive string or byte[] or something like that and take care of serialization/deserialization manually using something like JSON.Net. Personally I'd bite the bullet and make your types Data Contract Serializable until the new remoting bits are available.
With the release of Service Fabric V2 Remoting, this is now possible. See here for further details. Below
Here is an implementation of MessagePack remoting serializer I have used, but in your case the JSON example in the docs would probably suffice.
public class MessagePackMessageFactory : IServiceRemotingMessageBodyFactory
{
public IServiceRemotingRequestMessageBody CreateRequest(string interfaceName, string methodName, int numberOfParameters)
{
return new MessagePackRemotingRequestMessageBody(numberOfParameters);
}
public IServiceRemotingResponseMessageBody CreateResponse(string interfaceName, string methodName)
{
return new MessagePackServiceRemotingResponseMessageBody();
}
}
[MessagePackObject]
public class MessagePackRemotingRequestMessageBody : IServiceRemotingRequestMessageBody
{
[Key(0)]
public object Value;
public MessagePackRemotingRequestMessageBody()
{
}
public MessagePackRemotingRequestMessageBody(int parameterInfos)
{
}
public void SetParameter(int position, string paramName, object parameter)
{
Value = parameter;
}
public object GetParameter(int position, string paramName, Type paramType)
{
return Value;
}
}
[MessagePackObject]
public class MessagePackServiceRemotingResponseMessageBody : IServiceRemotingResponseMessageBody
{
[Key(0)]
public object Response;
public object Get(Type paramType)
{
// ignore paramType?
return Response;
}
public void Set(object response)
{
Response = response;
}
}
public class ServiceRemotingResponseMessagePackMessageBodySerializer : IServiceRemotingResponseMessageBodySerializer
{
public OutgoingMessageBody Serialize(IServiceRemotingResponseMessageBody responseMessageBody)
{
if (!(responseMessageBody is MessagePackServiceRemotingResponseMessageBody body))
{
return new OutgoingMessageBody(new[] { new ArraySegment<byte>(new byte[0]) });
}
var bytes = MessagePackSerializer.Serialize(body, ServiceFabricResolver.Instance);
return new OutgoingMessageBody(new[] { new ArraySegment<byte>(bytes) });
}
public IServiceRemotingResponseMessageBody Deserialize(IncomingMessageBody messageBody)
{
using (var stream = messageBody.GetReceivedBuffer())
{
if (stream.Length == 0)
{
return new MessagePackServiceRemotingResponseMessageBody();
}
var body = MessagePackSerializer.Deserialize<MessagePackServiceRemotingResponseMessageBody>(stream, ServiceFabricResolver.Instance);
return body;
}
}
}
public class ServiceRemotingMessagePackSerializationProvider : IServiceRemotingMessageSerializationProvider
{
public IServiceRemotingRequestMessageBodySerializer CreateRequestMessageSerializer(Type serviceInterfaceType,
IEnumerable<Type> requestBodyTypes)
{
return new ServiceRemotingRequestMessagePackMessageBodySerializer();
}
public IServiceRemotingResponseMessageBodySerializer CreateResponseMessageSerializer(Type serviceInterfaceType, IEnumerable<Type> responseBodyTypes)
{
return new ServiceRemotingResponseMessagePackMessageBodySerializer();
}
public IServiceRemotingMessageBodyFactory CreateMessageBodyFactory()
{
return new MessagePackMessageFactory();
}
}
public class ServiceRemotingRequestMessagePackMessageBodySerializer : IServiceRemotingRequestMessageBodySerializer
{
public OutgoingMessageBody Serialize(IServiceRemotingRequestMessageBody serviceRemotingRequestMessageBody)
{
if (serviceRemotingRequestMessageBody == null) return null;
if (!(serviceRemotingRequestMessageBody is MessagePackRemotingRequestMessageBody body))
{
return new OutgoingMessageBody(new[] { new ArraySegment<byte>(new byte[0]) });
}
var bytes = MessagePackSerializer.Serialize(body, ServiceFabricResolver.Instance);
return new OutgoingMessageBody(new[] { new ArraySegment<byte>(bytes) });
}
public IServiceRemotingRequestMessageBody Deserialize(IncomingMessageBody messageBody)
{
using (var stream = messageBody.GetReceivedBuffer())
{
if (stream.Length == 0)
{
return new MessagePackRemotingRequestMessageBody();
}
var body = MessagePackSerializer.Deserialize<MessagePackRemotingRequestMessageBody>(stream, ServiceFabricResolver.Instance);
return body;
}
}
}
I've been trying for ages to figure this our. when i try to bind my class with an interceptor i'm getting the following exception on the line
Kernel.Bind<MyClass>().ToSelf().Intercept().With<ILoggerAspect>();
Error loading Ninject component IAdviceFactory. No such component has been registered in the kernel's component container
I've tried with and without LoadExtensions, With about with using a Module to set up my bindings and my last attempt looks like this
internal class AppConfiguration
{
internal AppConfiguration( )
{
var settings = new NinjectSettings() { LoadExtensions = false };
Kernel = new StandardKernel(settings);
Load();
}
internal StandardKernel Kernel { get; set; }
public static AppConfiguration Instance
{
get { return _instance ?? (_instance = new AppConfiguration()); }
}
private static AppConfiguration _instance;
private void Load()
{
Kernel.Bind<ILoggerAspect>().To<Log4NetAspect>().InSingletonScope();
Kernel.Bind<MyClass>().ToSelf().Intercept().With<ILoggerAspect>();
}
internal static StandardKernel Resolver()
{
return Instance.Kernel;
}
}
My Logger Attribute looks like this
public class LogAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return request.Context.Kernel.Get<ILoggerAspect>();
}
}
And my interceptor like this
public class Log4NetAspect : SimpleInterceptor, ILoggerAspect
{
protected override void BeforeInvoke(IInvocation invocation)
{
Debug.WriteLine("Running " + invocation.ReturnValue);
base.BeforeInvoke(invocation);
}
public new void Intercept(IInvocation invocation)
{
try
{
base.Intercept(invocation);
}
catch (Exception e)
{
Debug.WriteLine("Exception: " + e.Message);
}
}
protected override void AfterInvoke(IInvocation invocation)
{
Debug.WriteLine("After Method");
base.AfterInvoke(invocation);
}
}
Most likely you didn't deploy Ninject.Extensions.Interception.DynamicProxy or Ninject.Extensions.Interception.Linfu alongside your application [and Ninject.Extensions.Interception]. You have to pick exactly one of them.
With the code as you have it right now (LoadExtensions=false) it will fail to pick up the specific interception library - you should remove that and the normal extensions loading should wire the extension into the Kernel on creation for the interception bits to pick it up.
In addition to Remo Gloor's answer which pointed me toward adding the nuget package for Ninject.Extensions.Interception.DynamicProxy, I kept getting the same exception as the OP, until I manually loaded a DynamicProxyModule - the FuncModule is manually loaded as well, to work around a similar error involving the factory extension:
_kernel = new StandardKernel(
new NinjectSettings{LoadExtensions = true},
new FuncModule(),
new DynamicProxyModule()); // <~ this is what fixed it
I have two tables, Locations and Facilities
They map to two classes,
public Location : Entity
{
//properties
}
public Facility : Entity
{
public virtual Location Location { get; set; }
}
Everything works just dandy, until I change facility to this
public Facility : Location
{
}
Now I get an exception from nHibernate saying
NHibernate.ADOException was unhandled by user code
Message=could not execute query
InnerException: System.Data.SqlClient.SqlException
Message=Invalid object name 'Facility'.
For some reason it is not creating the plural name of the table into the sql string.
Thanks for any help!
EDIT
This is my current TableNameConvention
public class TableNameConvention : IClassConvention
{
public void Apply(FluentNHibernate.Conventions.Instances.IClassInstance instance)
{
instance.Table(Inflector.Net.Inflector.Pluralize(instance.EntityType.Name));
}
}
When Facility inherits from Entity, the Facility does run through this method. When it inherits from Location, it does not
Edit 2
Figured I'd post everything...
public class AutoPersistenceModelGenerator : IAutoPersistenceModelGenerator
{
#region IAutoPersistenceModelGenerator Members
public AutoPersistenceModel Generate()
{
var mappings = new AutoPersistenceModel();
mappings.AddEntityAssembly(typeof(Person).Assembly).Where(GetAutoMappingFilter);
mappings.Conventions.Setup(GetConventions());
mappings.Setup(GetSetup());
mappings.IgnoreBase<Entity>();
mappings.IgnoreBase(typeof(EntityWithTypedId<>));
mappings.UseOverridesFromAssemblyOf<AutoPersistenceModelGenerator>();
return mappings;
}
#endregion
private Action<AutoMappingExpressions> GetSetup()
{
return c =>
{
c.FindIdentity = type => type.Name == "Id";
};
}
private Action<IConventionFinder> GetConventions()
{
return c =>
{
c.Add<BHP.DEC.Data.NHibernateMaps.Conventions.ForeignKeyConvention>();
c.Add<BHP.DEC.Data.NHibernateMaps.Conventions.HasManyConvention>();
c.Add<BHP.DEC.Data.NHibernateMaps.Conventions.HasManyToManyConvention>();
c.Add<BHP.DEC.Data.NHibernateMaps.Conventions.ManyToManyTableNameConvention>();
c.Add<BHP.DEC.Data.NHibernateMaps.Conventions.PrimaryKeyConvention>();
c.Add<BHP.DEC.Data.NHibernateMaps.Conventions.ReferenceConvention>();
c.Add<BHP.DEC.Data.NHibernateMaps.Conventions.TableNameConvention>();
};
}
/// <summary>
/// Provides a filter for only including types which inherit from the IEntityWithTypedId interface.
/// </summary>
private bool GetAutoMappingFilter(Type t)
{
return t.GetInterfaces().Any(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(IEntityWithTypedId<>));
}
}
Have you set a convention?
public class TableNameConvention : IClassConvention
{
public void Apply(FluentNHibernate.Conventions.Instances.IClassInstance instance)
{
string typeName = instance.EntityType.Name;
instance.Table(Inflector.Net.Inflector.Pluralize(typeName));
}
}
This is an old question, but for the sake of others who stumble upon this looking for an answer, you can also create a convention that uses the built-in PluralizationService that comes with EF:
public class TableNameConvention : IClassConvention
{
public void Apply(IClassInstance instance)
{
string typeName = instance.EntityType.Name;
instance.Table(PluralizationService.CreateService(CultureInfo.CurrentCulture).Pluralize(typeName));
}
}
In my quest for a version-wide database filter for an application, I have written the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluentNHibernate.Automapping;
using FluentNHibernate.Automapping.Alterations;
using FluentNHibernate.Mapping;
using MvcExtensions.Model;
using NHibernate;
namespace MvcExtensions.Services.Impl.FluentNHibernate
{
public interface IVersionAware
{
string Version { get; set; }
}
public class VersionFilter : FilterDefinition
{
const string FILTERNAME = "MyVersionFilter";
const string COLUMNNAME = "Version";
public VersionFilter()
{
this.WithName(FILTERNAME)
.WithCondition("Version = :"+COLUMNNAME)
.AddParameter(COLUMNNAME, NHibernateUtil.String );
}
public static void EnableVersionFilter(ISession session,string version)
{
session.EnableFilter(FILTERNAME).SetParameter(COLUMNNAME, version);
}
public static void DisableVersionFilter(ISession session)
{
session.DisableFilter(FILTERNAME);
}
}
public class VersionAwareOverride : IAutoMappingOverride<IVersionAware>
{
#region IAutoMappingOverride<IVersionAware> Members
public void Override(AutoMapping<IVersionAware> mapping)
{
mapping.ApplyFilter<VersionFilter>();
}
#endregion
}
}
But, since overrides do not work on interfaces, I am looking for a way to implement this.
Currently I'm using this (rather cumbersome) way for each class that implements the interface :
public class SomeVersionedEntity : IModelId, IVersionAware
{
public virtual int Id { get; set; }
public virtual string Version { get; set; }
}
public class SomeVersionedEntityOverride : IAutoMappingOverride<SomeVersionedEntity>
{
#region IAutoMappingOverride<SomeVersionedEntity> Members
public void Override(AutoMapping<SomeVersionedEntity> mapping)
{
mapping.ApplyFilter<VersionFilter>();
}
#endregion
}
I have been looking at IClassmap interfaces etc, but they do not seem to provide a way to access the ApplyFilter method, so I have not got a clue here...
Since I am probably not the first one who has this problem, I am quite sure that it should be possible; I am just not quite sure how this works..
EDIT :
I have gotten a bit closer to a generic solution:
This is the way I tried to solve it :
Using a generic class to implement alterations to classes implementing an interface :
public abstract class AutomappingInterfaceAlteration<I> : IAutoMappingAlteration
{
public void Alter(AutoPersistenceModel model)
{
model.OverrideAll(map =>
{
var recordType = map.GetType().GetGenericArguments().Single();
if (typeof(I).IsAssignableFrom(recordType))
{
this.GetType().GetMethod("overrideStuff").MakeGenericMethod(recordType).Invoke(this, new object[] { model });
}
});
}
public void overrideStuff<T>(AutoPersistenceModel pm) where T : I
{
pm.Override<T>( a => Override(a));
}
public abstract void Override<T>(AutoMapping<T> am) where T:I;
}
And a specific implementation :
public class VersionAwareAlteration : AutomappingInterfaceAlteration<IVersionAware>
{
public override void Override<T>(AutoMapping<T> am)
{
am.Map(x => x.Version).Column("VersionTest");
am.ApplyFilter<VersionFilter>();
}
}
Unfortunately I get the following error now :
[InvalidOperationException: Collection was modified; enumeration operation may not execute.]
System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) +51
System.Collections.Generic.Enumerator.MoveNextRare() +7661017
System.Collections.Generic.Enumerator.MoveNext() +61
System.Linq.WhereListIterator`1.MoveNext() +156
FluentNHibernate.Utils.CollectionExtensions.Each(IEnumerable`1 enumerable, Action`1 each) +239
FluentNHibernate.Automapping.AutoMapper.ApplyOverrides(Type classType, IList`1 mappedProperties, ClassMappingBase mapping) +345
FluentNHibernate.Automapping.AutoMapper.MergeMap(Type classType, ClassMappingBase mapping, IList`1 mappedProperties) +43
FluentNHibernate.Automapping.AutoMapper.Map(Type classType, List`1 types) +566
FluentNHibernate.Automapping.AutoPersistenceModel.AddMapping(Type type) +85
FluentNHibernate.Automapping.AutoPersistenceModel.CompileMappings() +746
EDIT 2 : I managed to get a bit further; I now invoke "Override" using reflection for each class that implements the interface :
public abstract class PersistenceOverride<I>
{
public void DoOverrides(AutoPersistenceModel model,IEnumerable<Type> Mytypes)
{
foreach(var t in Mytypes.Where(x=>typeof(I).IsAssignableFrom(x)))
ManualOverride(t,model);
}
private void ManualOverride(Type recordType,AutoPersistenceModel model)
{
var t_amt = typeof(AutoMapping<>).MakeGenericType(recordType);
var t_act = typeof(Action<>).MakeGenericType(t_amt);
var m = typeof(PersistenceOverride<I>)
.GetMethod("MyOverride")
.MakeGenericMethod(recordType)
.Invoke(this, null);
model.GetType().GetMethod("Override").MakeGenericMethod(recordType).Invoke(model, new object[] { m });
}
public abstract Action<AutoMapping<T>> MyOverride<T>() where T:I;
}
public class VersionAwareOverride : PersistenceOverride<IVersionAware>
{
public override Action<AutoMapping<T>> MyOverride<T>()
{
return am =>
{
am.Map(x => x.Version).Column(VersionFilter.COLUMNNAME);
am.ApplyFilter<VersionFilter>();
};
}
}
However, for one reason or another my generated hbm files do not contain any "filter" fields....
Maybe somebody could help me a bit further now ??
Apparently, there was a bug in the current version of fluent-nhibernate. The filters did not get copied when you use Automapper.Override<T> .
I forked the source, fixed the bug, tested, and I have now sent a pull request to the fluentnhib guys over at github.
For now, you can download the fixed sourcecode at http://github.com/ToJans/fluent-nhibernate/commit/29058de9b2bc3af85bc433aa6f71549f7b5d8e04
There is now also a complete blog post on how to do this :
http://www.corebvba.be/blog/post/How-to-override-interface-mappings-and-creata-a-generic-entity-version-filter-in-fluent-nhibernate.aspx