Fluent NHibernate and NLog - c#

I'm having issues with some vague errors popping out of my fluent configuration. I have read that setting up a logging solution will help me zero in on the issue. I would like to use NLog. I understand that I need to use Common.Logging 2.0 and NHibernate.IInterfaceLogger to get it up and running. I'm just not sure how to put the pieces together. My system is based off of the Onion Architecture. I have my Logging service set up for NLog and I have my interface for it, but I'm just a bit confused on where I should bind all of this together. My Fluent NHibernate configuration exists in my Data project. I'm assuming I would want to bind all of this together there.
Any thoughts on this would be awesome! I'm a little lost!

NHibernate.NLog nuget package does this. I use it in a project now.
For the sake of completeness or if that package ever disappears or the user doesn't use nuget.
You add this to your FluentConfiguration:
.ExposeConfiguration(c =>
{
c.SetProperty(#"nhibernate-logger", #"Microfilm.Core.NLogFactory, Microfilm.Core");
})
Implement ILoggerFactory to return a class that implements IInternalLogger. It's pretty straightforward what to include in the IInternalLogger methods; you're just bridging the calls for the NHibernate logger to NLog calls.

Related

Msoft.Practices.Unity injection of a library that uses services pattern

Good Morning,
I have a legacy full framework(4.7) MVC application. This application uses unity for DI.
We need to make use of the Steeltoe.CloudFoundry.Connector.Redis nuget package. This package however is expecting / used by startup.cs which I don't have.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddRedisConnectionMultiplexer(Configuration);
.PersistKeysToRedis();
services.AddDistributedRedisCache(Configuration);
}
What I am trying to figure out is how to use this with unity so I can have the Steeltoe redis connection object available for DI.
Since the steeltoe projects is OSS I could just grab the source and implement directly but then I have to maintain it.
(Speculation) I could have unity generate specific classes in the nuget package...
using Steeltoe.CloudFoundry.Connector.Redis;
....
container.Resolve(RedisCacheServiceCollectionExtensions)
Any other ideas?
TIA
You could do the initial implementation under Steeltoe, submit a pull request and let the community maintain it from there.
Steeltoe's lack of support for any given DI framework isn't intentional, but rather due to a lack of pre-existing demand. We'd be happy to help you through the process of getting the code included if you're interested.

Register the DbContext in my repository instead of the WebApi

I have a question regarding the repository and service pattern in combination with ASP.NET Core and EF Core. I'm in the stage of learning all of this, so I might miss the clear picture fully in front of me right now.
My current project structure looks as follows:
Project.Repository.Contracts
Project.Repository.EF
Project.Repository.FakeData
Project.Service.Contracts
Project.Service
Project.WebAPI
WebApp
In my understanding of the repository pattern, only the Project.Repository.EF project does know about EntityFramework.
But all "Repository, Service, ASP, EF" examples register the DbContext in the ConfigureService method in the WebAPI. By calling services.AddDbContext.
Isn't this a break of the concept?
I want to avoid to have the EntityFramework dependency in my WebApi.
So my question is, how can i archieve this?
This is my code so far:
WebApp.Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
Project.WebApi.Module.ConfigureServices(services);
services.AddAutoMapper();
}
}
Project.WebAPI.Module.cs
public class Module
{
public static void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IProjectService, ProjectService>();
services.AddSingleton<IProjectRepository, ProjectRepositoryEF>();
}
}
The Service and Repository are just stubs at the moment.
So again, what I want to avoid is, that I have to call services.AddDbContext in my Project.WebAPI.Module.cs class.
What I want to, is to register the DbContext in my Project.Repository.EF Project without hardcoupling it with my WebAPI.
Is this even possible?
Ok so let me make it a bit clearer for you.
The Repository pattern is more than just a data access layer that does some CRUD operations but I will try to limit my answer just to your problem to help you understand it.
(Keep in mind that the answer below is only relevant if you have a need to use repositories)
First lets talk a bit the naming of your projects.
The project Project.Repository.Contracts should be renamed to Project.Repository.DTOs to make it clearer.
This project contains Data Transfer Objects which is what your DataContext will use to generate your db and handle all the operations.
Then the Project.Service.Contracts can be renamed to Project.Domain in which you will have all your business logic related models.
Automapper will be used to do the two way mapping from dtos to domain objects and vice versa.
Now we will have to split your Project.Repository.EF project to two different projects.
You see, the repositories only need to know about the data context. EF doesn't need to know about the repositories.
So from the Project.Repository.EF project you will create Project.Data and Project.Repository
Your migrations and data context itself is in the Data project while the repositories are in the Repository project which references the Data project.
Now the Data project can be refered in the API project in order to be used in the startup class and as long as the services only know about the repositories project (and the web project only about services), you should be fine.
I would also make an extension method in the Data project instead of a static call like this Project.WebApi.Module.ConfigureServices(services);. It's cleaner.
You can also have your Startup class in a shared project between the dependencies and reference this single project on the project from which you start the host as well. Keep in mind that both DbContext, Services and repositories need to be configured at the IoC somehow. My cuppa is to create assembly markers and use Scrutor to scan for these dependencies.
EDIT: As Camilo suggested however, there's absolutely no need for a repository pattern in Entity Framework Core. EF Core is based on interfaces so you can implement your own classes around them.
The main reason why you would need a repository on top of EF was mocking.
This is no longer needed because:
In memory database built-in into EF Core
Is based on interfaces so you can implement your own classes around them
This may not be the best answer or the one you're looking for, but I hope it helps.
Isn't this a break of the concept?
From an idealistic view, perhaps. The important portion that you're separating out into another project(s) is the implementation of your repository, the setup of your context (mappings, etc).
The value in that is two-fold (at least):
You can reuse these in other projects
You can switch them out with a different implementation (with a matching interface) within the same WebAPI project. For instance, if you were supporting a legacy database and a new database.
Is this even possible?
Possibly with extra work and complexity, but is it practical? IME, I haven't seen a situation where it would improve the readability and maintainability of the code.
The question I would ask is, Am I going to need to dynamically choose between EF and a completely different repository type (such as Dapper, NHibernate, etc)? If the answer is no, or even not in the near future, I wouldn't add to the complexity.
As my grandmother used to say, "Don't borrow trouble." If you do need to completely switch to a different repository framework / ORM down the road, switching out the lines in ConfigureServices will be trivial. It's only complicated if you need to support two or more at once.

Design principles to consider when wrapping a 3rd party logger like log4net

I'm creating a logger for a company that has several types of .NET projects (Windows Services, ASP.NET, etc), and I was considering using log4net as my logger, but I don't want to be married to log4net, so I was thinking of wrapping it in my own assembly. I realize some developers don't recommend wrapping log4net because that would be an anti-pattern, but assuming I was going that route anyway, I had some questions:
I am planning to use the design principles mentioned in this article to design my wrapper (using factory method, interfaces, and reflection, I can simply decide which logger I want to use (whether log4net, elmah or something else) by specifying in the config file:
https://www.simple-talk.com/dotnet/.net-framework/designing-c-software-with-interfaces/
Question is:
Should I create this logger project in a separate Visual Studio solution and just use the dll in my client applications? If so, where would the configuration details for log4net go? Would that be supplied by the client application's config file? If so, is that good design? For instance, if I decided to switch away from log4net to a different logging framework, I would not only have to change the config setting to specify the new concrete logger's assembly/class name, but would also have to remove the log4net config entries (and perhaps add the new logger's config entries). Is this considered as an acceptable design approach?
Oh my goodness your timing is awesome. And that article is very relevant to me so thanks! I am doing this very same thing right now. I realized that log4net is a decent logger, but a terrible library for making a logger.
I agree with the article, in that you should not directly expose to log4net. Unless this is a small app it would be too difficult to switch later. And log4net is showing age so that may happen. I like the interface approach overall.
But, wrapping log4net it is a pain in the butt. So in doing my prototype wrapper I feel like I rewrote 50% of log4net, and discarded 25%. Some issues I found:
log4net will grab the "caller information" for you. Normally that is great. But if you wrap log4net, the caller information will point to your logger. So you will have to explicitly grab it yourself. But log4net doesn't provide a way for you to override the caller information. So now you will have to create your own fields for the caller's file, line number, class, and package. Thus, not only do you not gain the benefit here, but it is actually more work than just doing it yourself.
Log4net uses the old pre C#-4.0 method of grabbing the caller information which is slow.
Your will be unable to completely wrap log4net without wrapping the configuration. The caller has to configure the loggers either in code or in their app.config. If they do it in their app.config then they are putting log4net specific stuff in their app, so you failed to hide it with your wrapper. But if you have your wrapper code automatically perform the configuration, you just lost the flexibility of log4net. The third option is to make your own configuration, but then what good did log4net do for you? You just rewrote another piece of it.
You are stuck with the log levels that come with log4net. In our app, we want "categories" instead of "levels" which I then have to map to the log4net "levels" under the hood. Now, all the predefined log4net filters are of no use to me.
Anyone using your wrapper still has to reference log4net in their project anyway.
If your wrapper needs a way to handle errors, or pass them back to the caller, you will have trouble. log4net has its own internal error handling and you will need to hook into that and provide your own. Otherwise, errors (like a misconfigured appender) will just go out to the console. If it was designed as a library for making loggers, it would just throw the exception back up or provide a simple event.
One thing we wanted to get out of log4net is the ability to write to different outputs without us us having to write that code ourselves. Ex: I've never written to the event log, and I think log4net can do that. But it might be easier for me to rip out the Event logging code, rather than to try and wrap that. Same thing with filters.
There are some other problems I had with log4net that aren't directly related to trying to wrap it necessarily.
The code is old. The interfaces don't use generics where they should. Lots of object.
They use the old System.Collections collections. Similar to #1.
It has ifdefs for .NET 1 versus 2, and ifdefs for the obsolete compact framework. ugh.
It is designed to log strings, not structured objects. I made my own code to do so, and so did these people: http://stephenjamescode.blogspot.com/2014/01/logging-custom-objects-and-fields-with.html and http://element533.blogspot.com/2010/05/mapping-message-object-properties-to.html but this feels like basic functionality.
It doesn't support CSV and it is cumbersome to add. http://element533.blogspot.com/2010/05/writing-to-csv-using-log4net.html
It doesn't have any kind of logging "service"
It doesn't provide a way to read or parse the log.
I found it was more effort to configure the appenders than to write your own. Ex: I mapped a bunch of fields to the AdoNetAppender, but it would have taken me less time to just rewrite AdoNetAppender. Debugging a database field mapping in XML is harder than trying to debug the equivalent C# + ADO.NET code. The XML is more verbose and less type safe. This might be specific to me because I had a very structured set of data and a lot of fields.
Sorry for the really long post, I have lots and lots of thoughts on this topic. I don't really dislike log4net, I just think it is out of date and if you are wrapping it, you might be better off writing your own.

How can I log without polluting method?

I know about AOP and Postsharp but here the constraint is I can't use postsharp and using attributes for logging is having performance overhead.
But again right now I have to put log code in everymethod, a lot of copy paste and also it is not part of method. So, my functions are doing more than one work. It is somewhat not looks good to have business logic and log together.
Is there anyway out, like to make class open ended and can add log from out side of the class or function. Or I just have to go with traditional way of logging.
Please, let me know if any further information needed. Any suggestion of good/ another way of logging is also welcomed.
Enterprise Library and Unity. You can use composition to create logging decorators around other classes that log then pass-through to the other class.
Check out msdn.microsoft.com/en-us/magazine/gg490353.aspx
Hi as Peter Ritchie told, http://msdn.microsoft.com/en-us/magazine/gg490353.aspx is good solution. You can aslo take a look at http://www.microsoft.com/en-us/download/details.aspx?id=17866 or to other DI framework like Ninject this is good one for MVC projects.
Any way this is good articale about DI perfomance http://www.palmmedia.de/Blog/2011/8/30/ioc-container-benchmark-performance-comparison.
You can create decorators for your classes, take a look http://en.wikipedia.org/wiki/Decorator_pattern

How to conditionally enable actions in C# ASP.NET website

Using a configuration file I want to enable myself to turn on and off things like (third party) logging and using a cache in a C# website. The solution should not be restricted to logging and caching in particular but more general, so I can use it for other things as well.
I have a configuration xml file in which I can assert that logging and caching should be turned on or off (it could also be in the Web.Config, that's not the point right now) which will result in for example a bool logging and a bool caching that are true or false.
The question is about this part:
What I can do is prepend every logging/caching related statement with if (logging) and if (caching).
What is better way of programming this? Is there also a programming term for this kind of problem? Maybe attributes are also a way to go?
Why not just use the web.config and the System.Configuration functionality that already exists?
Your web app is going to parse web.config on every page load anyway, so the overhead involved in having yet another XML config file seems overkill when you can just define your own section on the existing configuration.
I'm curious what kind of logging/caching statements you have? If you have some class that is doing WriteLog or StoreCahce or whatever... why not just put the if(logging) in the WriteLog method. It seems like if you put all of your logging caching related methods into once class and that class knew whether logging/caching was on, then you could save your self a bunch of If statements at each instance.
You could check out the Microsoft Enterprise Library. It features stuff like logging and caching. The logging is made easy by the fact you always include the logging code but the actual logging beneath it is controlled by the settings.
http://msdn.microsoft.com/en-us/library/cc467894.aspx
You can find other cool stuff in the patterns and practices group.
Consult http://msdn.microsoft.com/en-us/library/ms178606.aspx for specifics regarding configuring cache.
I agree with foxxtrot, you want to use the web.config and add in a appsetting or two to hold the values.
Then for the implementation on checking, yes, simply use an if to see if you need to do the action. I highly recommend centralizing your logging classes to prevent duplication of code.
You could use a dependency injection container and have it load different logging and caching objects based on configuration. If you wanted to enable logging, you would specify an active Logging object/provider in config; if you wanted to then disable it, you could have the DI inject a "dummy" logging provider that did not log anything but returned right away.
I would lean toward a simpler design such as the one proposed by #foxxtrot, but runtime swapping out of utility components is one of the things that DI can do for you that is kind of nice.

Categories

Resources