I need a solution for logging and save the database user actions in the system, I need to record the User, the entity, the previous state and the current state of the entity and the date that the user made the change. I am using NHibernate,Autofac and .net 4.0 c#. I thought of creating an attribute filter and put in methods that need to generate the log, but also have interceptors that were created with the Autofac, but still can not think of the best solution, I really need help because they still have not implemented anything like
You could use some Listeners in Nhibernate. It works like triggers in database but in the ORM level. For sample, on PreUpdate method, you could take the old state and the new state of the object the ORM are changing and track some log. If you have a user logged on your AppDomain, you could take this information from the IPrincipal object. You have to inherit from the interfaces like IPreUpdateEventListener and IPreInsertEventListener and implement some method of these interfaces in a class. After it, configure your SessionFactory to use these listeners. There a lot of listerners you can see here.
Look these links:
http://darrell.mozingo.net/2009/08/31/auditing-with-nhibernate-listeners/
http://ayende.com/blog/3987/nhibernate-ipreupdateeventlistener-ipreinserteventlistener
http://nhibernate.info/doc/howto/various/creating-an-audit-log-using-nhibernate-events.html
PS: When you set a listener, it will work for every entity, do not forget to check the type you want to add this behaviour.
To audit database changes I can recommend NHibernate.Envers. I've used it in a previous project with good results.
NHibernate.Envers
Related
In an ASP.NET or MVC website project (or any other) where and how a collection of users taken from the database should be placed?
For example, I have a table of users in the database and I want to load it once to the memory as a dictionary of <UserId,User> and perform all the operations on it (and from it to the database).
The collection should be accessible from all of the pages/controllers.
What will be the "Best practices" way to do that?
Should I create a static object called Users that will contained the dictionary and some methods (add, remove, etc.) also as static?
Or should it be a non static object with a static dictionary inside it? and if so, where should it be placed?
Or maybe I am thinking of it in a totally wrong way?
Sorry if my question is not 100% clear, I just gave an example that I think can illustrate the scenario.
It seems to me like a basic issue but I am really confused about the right way of designing it.
For our WCF server, we used a static object that contained a table of users and their authorizations. This worked well and prevented frequent database round-trips on every connection.
The real challenge was ensuring this table was up-to-date when user accounts change. We implemented a state refresh mechanism. When someone saves a change to user accounts, the web service detects this change and refreshes its state information.
Note that the .NET Framework 4.0 and higher a MemoryCache class built in.
First of all, using static objects (static properties) in a web application is a horrible idea. Concurrency becomes an issue and weird things with user values changing due to other user input (since a static object is shared across the whole app domain) become apparent.
A static read-only object is an exception to the above.
Probably the best way to handle the scenario in your question is using caching. Cache the list, and then rebuild the cache each time after any updates.
If using .net 4.0 or above, take a look at the System.Runtime.Caching namespace. It is similar to the old System.Web.Caching namespace from earlier versions, but now available to the entire .net framework, and also extensible if needed.
This will take care of "where to put the data".
Then you can implement a Business Logic Layer that handles pulling data from the cache and sending to the UI, communicate with data layer, update the cache after any database updates are performed, etc.
That's how I'd do something like this.
I'm working with repositories and one thing I'm really working hard on is to make things as most decoupled as they can. So, if tomorrow we change from relational databases to something else, like NoSQL and things like that we are good to go, we just have to change our DAL.
I've been trying to find out how to implement the SaveChanges method in my WebAPI controller without needing to use the EFContextProvider. I've found then the Breeze NoDb sample, however this sample uses the Breeze ContextProvider in the repository. This is something that troubles me because Breeze is a JS library, so it is something about the presentation of my application. In that case, making the repository use a component from Breeze will couple the DAL and the presentation, something I don't want to do.
Searching again for how to implement SaveChanges without EF I've found this question where there's one very good answer telling how to convert the SaveBundle to a SaveMap and then tell to use this to implement the saving logic. However I'm stuck in this method because the entries of the SaveMap give just one Type object and the EntityInfo, so I don't see how to use this with my repositories.
So, how to deal with SaveChanges without to refer to EFContextProvider and without coupling the repositories with the ContextProvider?
Are you planning to switch from SQL Server to NoSQL database? why don't you want to do that just now? How often are you planning to switch backing storage? Probably not often, if ever.
I found that database switch, especially from SQL to NoSQL is a big shift in paradigm. In one of my application I've gone through conversion from SQL to RavenDb. Despite of having everything decoupled and with using Repositories everywhere, I still had to rewrite most of the application storage logic.
What you are trying to do - you are not going to need it. So stop making life hard for yourself and get on with implementing features.
The ContextProvider does the work of converting the JObject (which Json.NET gives you in the SaveChanges method), into real, typed .NET objects. The EntityInfo object that the ContextProvider creates for each entity contains the entity object itself, as well as the entityAspect properties that it got from the client: the EntityState (Added, Modified, or Deleted), the original values of all changed properties, and the temporary values for any auto-generated keys. This is the information that you would need to save the entities yourself. The "SaveMap" just organizes them by Type for convenience, but you can manipulate them however you like.
As described in the post you referenced, you could proceed by using a ContextProvider just to convert the JObject to entities, then pass those entities to the appropriate repositories. Your repositories don't need to know anything about the ContextProvider.
Breeze offers an NHibernate provider that you can look at that shows how to talk to a non EF backend that is still a .NET server. The ContextProvider is a convenence that makes implementing any .NET provider substantially easier, but it is by no means a requirement.
As for NoSQL you should take a look at the breeze Node provider and MongoDB sample which is hosted in NodeJs ( which shows that the ContextProvider is obviously not a requirement).
We also expect to have a Breeze server implementation written in Java in the near future, which again has no "ContextProvider" requirement.
The requirement seems simple: when data changes, audit the changes.
Here's some important pieces to the equation:
The Data in my application spans multiple tables (some cross ref. tables).
My DTO is deep, with Navigation Properties conditionally populated.
When loaded, I copy the original DTO with its "original values".
When saved is requested, the original DTO contains the changes.
Ideally, foreign keys will read like useful text not Id numbers.
Unlike TFS' cool history feature, mine seems more complicated because of the many related tables and conditional child entities.
I see three possibilities (so far):
I could use C# to reflect the objects and create a before/after record.
I could use triggers in SQL 2008R2 to catch changes and coalesce a before/after record.
I could store the raw before/after objects and let SQL 2008R2 parse them.
Please note: Right now, I seems to me that SQL 2008R2's CDC is far too heavy of an option. I am really looking for something I can build, but I admit my mind is open to anything right now.
My question
Before I get started building this:
How does everybody else handle auditing a complex EF DTO?
Is there a low(ish)-tech solution available?
Thank you in advance.
Related, but not-completely-related questions already on StackOverflow: Implementing Audit Log / Change History with MVC & Entity Framework and Create Data Audit in SQL Server and https://stackoverflow.com/questions/5773419/how-to-audit-many-to-many-relationship-in-entity-framework and Maintaining audit log for entities split across multiple tables and Linq to SQL Audit Trail / Audit Log: should I use triggers or doddleaudit? do not provide an answer.
IF audit is a real requirement I would opt for the trigger solution... since the other methods have several "shortcomings":
"blind" to any changes happening through other means than your application
if you make some code changes and forget about adding the audit code the audit trail gets "blind spots"
The trigger-based solution can be secured so that only special users can even see the audited data...
I usually work with Oracle but from my experience in such situations: allow the app only SELECT rights via Views , any insert/delete/update should be done via Stored procedures and audit trail should be done via triggers...
I've recently implemented an audit log manager on top of Entity Framework. When I instantiate my audit manager, I reflect all of the entity classes, and store the property information. Then within the object context SavingChanges event, I audit all of the changes. It works great. In the case of foreign keys, I just store their Id's before and after during changes.
The nice thing about this solution is that it doesn't require any extra coding. Once you create a log manager of sort, you don't have to worry about adding new triggers, or modifying triggers when new columns are added. Any changes to your entity classes will automatically be picked up when reflecting the classes.
Well, let's see. SQL Server auditing already exists, comes with tools, is probably already known by your DBAs, doesn't slow down your app, and can trace events that the application itself will never even see.
On the other hand, rolling your own in EF will allow you to audit non-SQL Server data sources. It also doesn't require EE.
Trigger Solution, Pros:
Cannot bypass the audit
Trigger Solution, Cons:
Cannot audit non SQL data
Cannot audit complex objects on insert
Entity Framework, Pros:
Can audit everything
Can audit complex objects in any state
Entity Framework, Cons:
Can be bypassed (like direct-to-SQL)
Requires a copy of original values
My choice is Entity Framework. Using STE makes it easier.
Either way you have to roll your own.
OK,
This is probably not simple but I figured I would throw it out there:
I get the idea of extending an Model-First entity in EF with a partial class to add data annotation elements somthing like this:
[Required]
string MyString {get;set;}
However, if I am in a multi-tenant system where I may want to customize which fields are actually required when passed to the end client can I dynamically set the annotation depending on how the client has configured the setting, say in another table for instance?
Update: In the multi-tenant system there are at least two databases. One that stores system configuration information. In addition each customer would have their own individual database. The system DB controls routing and selecting the proper customer database from there.
Any insights or ideas anyone has on how to accomplish this would be great!
Thanks,
Brent
If you are using EF 4.1, you could create different DbContexts, referencing the same entities, but provide different mappings using the Fluent Api.
Here is a link to a video that describes using the api.
Fluent Api
Note: Your database would need to be setup to accommodate all the different configurations. For example, if in one context, "FirstName" is required, and in another it is not, your db should allow NULL in order to cope with both situations.
You can't change attributes dynamically.
One option would be to crate the types dynamically, probably inheriting some class (or implementing an interface), that you actually work with. Although I'm not sure this would work with EF.
Another possibility is if EF had another way you could tell it the same thing, but I don't know EF much, so I can't tell if something like that exists.
If I wanted to access a database in Delphi, I could add a datamodule to a project, configure it from my mainform and then access it anywhere in the application; a reference would be stored in a global variable.
I know that in C# and other more modern OO languages global variables are frowned upon. So how can I access my database from where I need it? The biggest problem I have is the configuration: location, user, password, etc. are unknown at design time.
I now have a db-class and make a new instance when I need it, but then I would have to store those settings in some globally accessible thing, and I have simply moved the problem.
What's the standard solution?
Thanks, regards, Miel.
I always use the singleton pattern. As for configuration, look at the System.Configuration.ConfigurationManager class which allows you to read settings from your project's app.config/web.config file.
It's a bit tricky to define the absolute best practice for database access in OOP.
You've hit the nail on the head that there are a lot of factors to consider:
how are configuration parameters handled?
is the app multi-threaded? do you need database connection pools?
do you need database portability (ie: do you use different DBs in dev versus production? are you concerned about vendor lock-in with one DB? Are you distributing the app the other users who may be using a different db?)
are you concerned with securing your SQL statements, or centrally enforcing other access permissions?
is there common logic involved when performing some inserts and updates that you'd rather not duplicate everywhere a particular table is touched?
Because of this, many OOP folks gravitate to an ORM framework for anything but the simplest cases. The general idea is that your application logic shouldn't need to talk to the database directly at any point: isolate your business code from the actual persistence mechanism for as long as possible.
Instead, try to design your application so that your business logic talks to a model layer. In other words, have model objects in the system that encapsulate and describe your business data. These model objects then expose methods for obtaining and saving their state into the database, but your logic doesn't need to care about that.
For example, say you have a concept called "Person" in your system. You'd probably model this as a class with some properties. In pseudo-code:
Person:
- first_name
- last_name
Your actual code in the system is then only concerned with instantiating and using Person objects, not with obtaining DB handles or writing SQL:
p = Person.get(first_name='Joe')
p.last_name = 'Bloggs'
p.save()
In an object-oriented world, you'll find that your business logic code becomes cleaner (and shorter!), easier to maintain, and much more testable.
Of course, you're right in that this means you need to now go off and build a database back-end that translates that Person class to one or more tables in your relational database. This is where using an ORM framework comes in handy. In Python, people use Django and SQLAlchemy. I'll let others indicate what folks use in C# (I'm not a C# developer, but you did tag your question OOP, so I'm going for the generic answer here, rather than C# specific).
The point, though, is that the ORM framework puts all the DB access in a single set of classes in the code, so that the DB access, configuration and pools are handled in one place... no need to instantiate them all over the application. What you use "where you need it" is the model object.
Of course, if your app is very simple and you want just a raw DB handle, then I do recommend the dependency injection approach others have listed.
Hope that helps.
It seems to me that you need to create an appropriate object (containing the connection or similar), and pass that instance to each object requiring access (see dependency injection)
This is different from using singletons. By using this mechanism, it'll free you from the dependency on one object and (perhaps a more compelling reason in this instance) allow you to perform testing by injecting mock objects or similar in place of the originally-injected database accessor object. I would definitely shy away from the singleton mechanism in this scenario.
I actually use a repository class that takes in the db information in its constructor and have the classes that need it get it passed in. I actually use an Inversion of Control (IOC) tool to inject that values in.
You could store the user information in a flat file somewhere, then read / write to it from your db-class
This way you won't duplicate the settings in your code, but the user can still modify the settings.
SubSonic is the "Swiss Army knife" for object relational mapping, and offers the ability to execute stored procedures and return results to List. You can have it up and running within a half hour.