Second DB Context not usable in unit tests - asp.net-boilerplate

After I managed to get multiple Database Context working in asp.net boilerplate (with some help here ASP.NET Boilerplate multiple databases and DbContexts), I ran into another problem. In the unit tests, when I use one of the additional database contexts like so:
using (var uow = this.UnitOfWorkManager.Begin())
{
var r = this.SlipLineRepository.GetAll().ToList();
}
I get this error:
Abp.AbpException : Could not resolve DbContextOptions for SlipStreamAPI.SlipStreamDB.miSlipLiveContext, SlipStreamAPI.EntityFrameworkCore, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
So my questions are:
1) Is it possible to test against in memory DB contexts, if they are the second, third, etc context?
2) If it is, what should I do to make it work?

You should register DbContextOptions in ServiceCollectionRegistrar.cs:
public static void Register(IIocManager iocManager)
{
// ...
var builder = new DbContextOptionsBuilder<miSlipLiveContext>();
builder.UseInMemoryDatabase(Guid.NewGuid().ToString()).UseInternalServiceProvider(serviceProvider);
iocManager.IocContainer.Register(
Component
.For<DbContextOptions<miSlipLiveContext>>()
.Instance(builder.Options)
.LifestyleSingleton()
);
}

Related

View NotFound Exception in net core6

I wanna Render View To Stream.
this is my code:
var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };
var actionContext = new ActionContext(httpContext, new
RouteData(), new ActionDescriptor());
var viewEngineResult = _viewEngine.FindView(actionContext,
viewName, false);
this code worked before. but after update to core6 doesn't work.
net core 6 does not create view.dll
my razor view is in Views/Shared location. and i set it as content
Compiler no longer produces a Views assembly
The Razor compiler no longer produces a separate Views.dll file that
contains the CSHTML views defined in an application.
Both views and application types are included in a single
AppName.dll assembly. View types have the accessibility modifiers
internal and sealed, by default, and are included under the
AspNetCoreGeneratedDocument namespace.
So, If your method is doing something by View.dll, It is not work in .Net 6
Refer to this doc to learn more.

How do I use Castle Windsor to create a RavenDB session with client version > 3.0.3660?

I am using Castle Windsor v3.4.0 to create a RavenDB document session instance but when I use a RavenDB client version later than 3.0.3660 I get this error when calling the Store method:
Castle.MicroKernel.ComponentNotFoundException: 'No component for supporting the service System.Net.Http.HttpMessageHandler was found'
Here is the smallest piece code I can come up with that reproduces the error:
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Raven.Client;
using Raven.Client.Document;
public class Program
{
public static void Main()
{
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component
.For<IDocumentStore>()
.ImplementedBy<DocumentStore>()
.DependsOn(new { Url = "http://localhost:8081", DefaultDatabase = "Test" })
.OnCreate(x => x.Initialize())
.LifeStyle.Singleton,
Component
.For<IDocumentSession>()
.UsingFactoryMethod(x => x.Resolve<IDocumentStore>().OpenSession())
.LifeStyle.Transient);
using (var documentSession = container.Resolve<IDocumentSession>())
{
documentSession.Store(new object());
documentSession.SaveChanges();
}
}
}
Here's what I believe is happening. A change was made to the RavenDB client after v3.0.3660 that changed how the HttpMessageHandler is created in the HttpJsonRequest class:
https://github.com/ravendb/ravendb/commit/740ad10d42d50b1eff0fc89d1a6894fd57578984
I believe that this change in combination with my use of the TypedFactoryFacility in my Windsor container is causing RavenDB to request an instance of HttpJsonRequestFactory and it's dependencies from Windsor rather than using it's own internal one.
How I can change my code to avoid this problem so that I can use a more recent version of the RavenDB client?
Given your MVCE, Windsor is set up to inject object's properties. So, when creating the DocumentStore, Castle is trying to find a value for the HttpMessageHandlerFactory property and is failing since nothing is configured for that particular type.
I was able to get your example to work (at least, it got to inserting the data into my non-existing server) by just filtering out that property:
container.Register(
Component.For<IDocumentStore>()
.ImplementedBy<DocumentStore>()
.DependsOn(new { Url = "http://localhost:8081", DefaultDatabase = "Test" })
.OnCreate(x => x.Initialize())
.PropertiesIgnore(p => p.Name == nameof(DocumentStore.HttpMessageHandlerFactory))
.LifeStyle.Singleton);
Alternatively, if you have a value for it, you could add it to the object passed to DependsOn().

Resolve caste windsor failing

Recently upgraded to version 3.2.1 of castle windsor and receiving an error when attempting to resolve a service that previously didn't occur in version 3.0 of the windsor framework.
IWindsorContainer container = new WindsorContainer();
The following code no longer works
// Throws component not found exception
InstallerHelper.ProcessAssembliesInBinDirectory(
assembly => container.Register(
Classes
.FromAssembly(assembly)
.BasedOn<IWindsorInstaller>()
.WithService.FromInterface()
.LifestyleSingleton()
));
var installers = container.ResolveAll<IWindsorInstaller>();
container.Install(installers);
// Fails here, is it related to a hashcode mismatch in SimpleTypeEqualityComparer?
var credentialCache = container.Resolve<ICredentialCache>()
// works fine if explicity install installers individually
container.Install(new CredentialsInstaller());
var credentialCache = container.Resolve<ICredentialCache>()
Where ProcessAssembliesInBinDir is:
public static void ProcessAssembliesInBinDirectory(Action<Assembly> action)
{
var directoryName = GetDirectoryName();
foreach (var dll in Directory.GetFiles(directoryName, "*.dll"))
{
var fileInfo = new FileInfo(dll);
if (!IgnoreList.Any(x=>fileInfo.Name.StartsWith(x)))
{
var assembly = Assembly.LoadFile(dll);
action(assembly);
}
}
}
Where credential installer is:
public class CredentialsInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ICredentidalCache>()
.ImplementedBy<CredentidalCache>()
.LifestyleSingleton()
);
// This works fine
var credentialCache = container.Resolve<ICredentialCache>()
}
}
Class implementation
public interface ICredentidalCache {}
public class CredentidalCache : ICredentidalCache{}
This is being run from an MVC application
version 4.5 of the .net framework
the credential installer lives inside another assembly, referenced by the website
using the Windsor source, the successful attempt to resolve occurs when the typeof(ICredentialCache).GetHashCode() is the same as what has been registered. For some reason when returning out of the installer the hashcode has changed for the type. Putting a debug line inside SimpleTypeEqualityComparer.GetHashCode(Type obj) shows that hashcodes are different for the same Type.
inspecting the container inside the debugger shows the ICredentialCache successfully installed.
Edit
Manage to move forward by manually registering installers, ie. not relying on the resolve<IwindsorInstaller>() and use container.install(new Installer(), ...). If i find out more I'll update the SO question.
This works fine for me:
public sealed class AppServiceFactory
{
...
public T Create<T>()
{
return (T)container.Resolve(typeof(T));
}
...
}
AppServiceFactory.Instance.Create<IYourService>();
The problem is caused by the InstallerHelper and how it goes about loading an assembly. This SO post pointed me in the right direction,
https://stackoverflow.com/a/6675227/564957
essentially the way the assembly was loaded was failing using Assembly.LoadFile(string fileName) was causing the problem, changing this to be Assembly.Load(string assemblyName) rectified the issue.
#Eric Lippert does a good job explaining
[when] loading an assembly by its path, and one via loading the same
assembly by its assembly name... reflection will
consider types from the two loadings of the same assembly to be
different types. Any assembly loaded from its path is considered to be
distinct from an assembly loaded by its assembly name.

How are templates in RazorEngine cached?

When you call RazorEngine.Razor.Compile(), where is the compiled template stored?
Is it available after the programs been restarted? If there is a memory shortage, will it be dumped?
I am using RazorEngine in an ASP.NET (MVC) project. Will the precompiled templates be available after the application restarts?
Would it make more sense for me to store them in the HttpContext.Cache?
If I did, then would it make more sense to use a different function (other than Compile) that bypasses the internal cache? Is there a way to execute an ITemplate and just pass it a model?
Does RazorEngine.Razor.Parse() do any caching? Or is the template recompiled each time?
Currently, after the RazorEngine compiles the templates, they are loaded into memory. These assemblies persist in memory only and do not continue beyond the lifetime of the application.
I am considering adding in support for compiling these assemblies to files, but that'll be a future version.
If you call Razor.Parse and pass in a name for the template, it will attempt to
Check the cache of in-memory assemblies for an assembly with the same name.
Invalid the cache of the content of the template has changed.
Cache the newly compiled template.
I've got this to work with RazorEngine 3.4.1.0, installed late Jan 2014.
The key is to call the expensive Razor.Compile(content, name) to put the template into cache, then call the cheap Razor.Run(name, model) to execute the template.
Remember that reading template content might be expensive -- say, involving a read from disk -- so my solution only gets template content once. This might be too much caching for you, so careful!
Here's the RenderPartial method I use inside a custom TemplateBase<T> subclass. It runs very quickly for multiple calls to the same template.
public abstract class SqlTemplate<T>: TemplateBase<T>
{
public string RenderPartial(string templateName, object model = null)
{
// loading a template might be expensive, so be careful to cache content
if (Razor.Resolve(templateName) == null)
{
// we've never seen this template before, so compile it and stick it in cache.
var templateContent = GetTemplateContent(templateName);
Razor.Compile(templateContent, templateName);
}
// by now, we know we've got a the template cached and ready to run; this is fast
var renderedContent = Razor.Run(templateName, model);
return renderedContent;
}
private string GetTemplateContent(string templateName)
{
... your implementation here
}
}
You also need to tell Razor to use this base class (SqlTempalte<T>) which you can do like this, by calling RazorEngineConfigurator.Configure();
public static class RazorEngineConfigurator
{
private static bool configured = false;
public static void Configure()
{
if (configured)
{
return;
}
var templateConfig = new TemplateServiceConfiguration
{
BaseTemplateType = typeof(SqlTemplate<>),
EncodedStringFactory = new RazorEngine.Text.RawStringFactory()
};
RazorEngine.Razor.SetTemplateService(new TemplateService(templateConfig));
configured = true;
}
}
Couldn't have done it without this SO answer -- why not give that one an up-vote, too? :)
Edit - If you need to perform caching in a more granular way, you'll need to use a different approach using RazorEngineTemplateService and ITemplateResolver.
Here's a piece of starter code;
public static RazorEngineTemplateService CreateService(ITemplateResolver resolver, ICollection<string> namespaces)
{
Check.IsNotNull(resolver, "resolver");
var config = new TemplateServiceConfiguration();
config.BaseTemplateType = typeof(PlainTextTemplate<>);
config.EncodedStringFactory = new RazorEngine.Text.RawStringFactory();
config.Resolver = resolver;
config.Namespaces = new HashSet<string>(namespaces);
var service = new RazorEngineTemplateService(config);
return service;
}
ITemplateResolver turns template names into template contents, so you can implement, eg, a CachedFileTemplateResolver which loads cached content from disk.

Hard to update an Entity created by another LINQ to SQL context

Why this keep bugging me all day.
I have an entity with several references where i get from a context which I then Dispose.
Do some Changes and try to SubmitChanges(). While calling SubmitChanges() without .Attach() seems to simply do nothing. When using .Attach() I get the Exception :
An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported.
Any ideas?
L2S is very picky about updating an entity that came from a different DB context. In fact, you cannot do it unless you 'detach' it first from the context it came from. There are a couple different ways of detaching an entity. One of them is shown below. This code would be in your entity class.
public virtual void Detach()
{
PropertyChanging = null;
PropertyChanged = null;
}
In addition to this, you can also serialize your entity using WCF based serialization. Something like this:
object ICloneable.Clone()
{
var serializer = new DataContractSerializer(GetType());
using (var ms = new System.IO.MemoryStream())
{
serializer.WriteObject(ms, this);
ms.Position = 0;
return serializer.ReadObject(ms);
}
}