I'm using NHibernate on a project and I need to do data auditing. I found this article on codeproject which discusses the IInterceptor interface.
What is your preferred way of auditing data? Do you use database triggers? Do you use something similar to what's dicussed in the article?
For NHibernate 2.0, you should also look at Event Listeners. These are the evolution of the IInterceptor interface and we use them successfully for auditing.
[EDIT]
Post NH2.0 release, please look at the Event Listeners as suggested below. My answer is outdated.
The IInterceptor is the recommended way to modify any data in nhibernate in a non-invasive fashion. It's also useful for decryption / encryption of data without your application code needing to know.
Triggers on the database are moving the responsibility of logging (an application concern) in to the DBMS layer which effectively ties your logging solution to your database platform. By encapsulating the auditing mechanics in the persistance layer you retain platform independance and code transportability.
I use Interceptors in production code to provide auditing in a few large systems.
I prefer the CodeProject approach you mentioned.
One problem with database triggers is that it leaves you no choice but to use Integrated Security coupled with ActiveDirectory as access to your SQL Server. The reason for that is that your connection should inherit the identity of the user who triggered the connection; if your application uses a named "sa" account or other user accounts, the "user" field will only reflect "sa".
This can be overriden by creating a named SQL Server account for each and every user of the application, but this will be impractical for non-intranet, public facing web applications, for example.
I do like the Interceptor approach mentioned, and use this on the project I'm currently working on.
However, one obvious disadvantage that deserves highlighting is that this approach will only audit data changes made via your application. Any direct data modifications such as ad-hoc SQL scripts that you may need to execute from time to time (it always happens!) won't be audited, unless you remember to perform the audit table insertions at the same time.
I understand this is an old question. But I would like to answer this in the light of the new Event System in NH 2.0. Event Listeners are better for auditing-like-functions than Interceptors. Ayende wrote a great example on his blog last month. Here's the URL to his blog post -
ayende.com/Blog/archive/2009/04/29/nhibernate-ipreupdateeventlistener-amp-ipreinserteventlistener.aspx
As an entirely different approach, you could use the decorator pattern with your repositories.
Say I have
public interface IRepository<EntityType> where EntityType:IAuditably
{
public void Save(EntityType entity);
}
Then, we'd have our NHibernateRepository:
public class NHibernateRepository<EntityType>:IRepository<EntityType>
{
/*...*/
public void Save ( EntityType entity )
{
session.SaveOrUpdate(entity);
}
}
Then we could have an Auditing Repository:
public class AuditingRepository<EntityType>:IRepository<EntityType>
{
/*...*/
public void Save ( EntityType entity )
{
entity.LastUser = security.CurrentUser;
entity.LastUpdate = DateTime.UtcNow;
innerRepository.Save(entity)
}
}
Then, using an IoC Framework (StructureMap, Castle Windsor, NInject) you could build it all up without the rest of your code every knowing you had auditing going on.
Of course, how you audit the elements of cascaded collections is another issue entirely...
Related
Some days I love my dba's, and then there is today...
In a Grails app, we use the database-migration plugin (based on Liquibase) to handle migrations etc.
All works lovely.
I have been informed that there is a set of db administrative meta data that we must support on every table. This information has zero use to the app.
Now, I can easily update my models to accommodate this. But that answer is ugly.
The problem is now at each migration, Liquibase/database-migration plugin, complains about the schema and the model being out of sync.
Is there anyway to tell Liquibase (or GORM) that columns x,y,z are to be ignored?
What I am trying to avoid is changesets like this:
changeSet(author: "cwright (generated)", id: "1333733941347-5") {
dropColumn(columnName: "BUILD_MONTH", tableName: "ASSIGNMENT") }
Which tries to bring the schema back in line with the model. Being able to annotate those columns as not applying to the model would be a good thing.
Sadly, you're probably better off defining your own mapping block and taking control of the Data Mapper (what Hibernate essentially is) yourself at this point. If you need to take control of the way the database-integration plugin handles migrations, you might wanna look at the source or raise an issue on the JIRA. Naively, mapping your columns explicitly in the domain model should allow you to bypass unnecessary columns from the DB.
I would like to use a local SQL Server CE in my app; I've read that using EF code-first I can let the system create the db starting from POCO classes; I've configured EFCodeFirst.SqlServerCompact using NuGet but it's not clear to me how can I use it in my WPF app....can anyone help me?
It doesn't really matter whether you use the default WPF style application development or MVVM pattern, as long as you have a separate data layer.
Your data layer should hide away all of the DB implementation logic, including the creation of the DB from the rest of your code.
You could implement it using the Repository pattern, but as long as it provides a known interface and definitions for the data objects that your business logic requires you should be okay.
Note that the data objects used by the other layers of code do not need to be the same as the POCO objects used by the DB.
If you have your data layer accessed by a Singleton class that implements the layer's interface then you could automatically call the DB creation code if the DB can not be found when DataLayer.Instance (for example) is called.
The important thing to remember is that only the internal workings of the datalayer should know where the data comes from the rest of your code should be DB agnostic, only caring that it has the data that it needs, not where it comes from.
As for practicalities here's a link that gives a Code First with EF example.
I'm busy learning Prism 4 and the in and outs of everything, but I've yet to see a tutorial/walk through on what I want to accomplish. Hoping someone here has or has worked on a similar project.
My application is a basic CRUD application that I've broken down in to separate areas of concern and hence modules. However, I want all the modules to share one common local SQL Express database. The database will start off with just a limited number of tables to start with and each module will check the database for the tables it needs and if they are not there, create them. How can I go about accomplishing this?
I've thought about just adding in all my tables initially but this seems to break the principal of modularity in my mind. Perhaps my thinking is wrong, but what would be the point of loosely coupled modules if the database is already fully aware and strongly coupled to a given module from db creation?
Looking for some insight.
You seem to be asking two questions. The first is: How can I use PRISM to ensure that my module specific schema exists in the database, and if not, create it. The second question is: how can I best structure my data layer such that it is decoupled in a modular application.
To answer your first question about how to do the module schema check, I say this:
If you’ve been going through Prism, you’ve no doubt thought up a couple of ways to accomplish it. As with anything in programming, there are many ways to accomplish it. If I needed to do this with Prism, I’d probably do the following: Create a class (MyPlugInModule.cs) in my module assembly which implements the Microsoft.Practices.Prism.Modularity.IModule interface. I would then put code in either the constructor, or in the Initialize method, which checks the database to see if the module schema exists. If it does not, then create it.
To answer your second question about how to best structure your data modularity, I say this:
Like Goblin says, it really depends on what type of modularity you are trying to accomplish. If you are selling this application and you want to sell modules as independent packages, then you probably do not want to create a data model to support a package until the end user has paid for it.
You should be able to use Entity Framework to ensure that your modules are able to share entities with the base application modules. Additionally, depending on what your requirements are, or if your architecture will allow, you may want to abstract your model/data layer into assemblies that are not perfectly aligned with your modules. This will reduce code duplication and dependencies.
On an application that I am currently working on, we're using WPF with MVVM, PRISM with MEF, and WCF data services. Our client modules share a data assembly which communicates with our main data service endpoint that sits on top of the base application model (authentication/role tables, application data, etc). When tables in our database are created that are specific to the domain of a module, a new model and service endpoint are created on the server, and a separate assembly is created on the client to communicate with the data model.
If the module specific model changes, only the affected components have to be changed, since module specific data is encapsulated in its own service and client assembly. It is a better option from an isolation standpoint for testing, security, etc. The downside of course is if the base application model changes, all of the associated module specific implementations have to be updated.
But again, it really depends on your requirements. If you stick with PRISM 4 with MEF, modular design patterns, and entity framework 4, you should be able to come up with a good solution that is modular without being tightly coupled.
If your modules are truly independent - how about a database per module? If you need foreign keys between your modules - they are in essense not really encapsulated - and I'd put the whole database into play from the get-go. Much easier to keep the schema up-to-date betweeen updates.
Modularity comes in many flavours - business-perspective (pay-per-module), modularity in terms of responsibilities etc. etc.
My 5 cents :)
This response is for anyone coming here that wants to see code that hooks up a local database. It works for me, not sure if it's best practice or not.
I'm using prism and I needed to get my database working. Here is what I did. The Entity Framework seems to "just work" for putting the database somewhere.
Bootstrapper.cs file:
....
protected override void ConfigureContainer() {
base.ConfigureContainer();
// Register my navigation
Container.RegisterType<IAppDatabaseContext, AppDatabaseContext>();
}
....
My AppDatabaseContext.cs file:
public class AppDatabaseContext : DbContext, IAppDatabaseContext {
DbSet<MyModelOne> MyModelOnes { get; set; }
DbSet<MyModelTwo> MyModelTwos { get; set; }
DbSet<MyModelThree> MyModelThrees { get; set; }
}
public interface IAppDatabaseContext {
DbSet<MyModelOne> MyModelOnes { get; set; }
DbSet<MyModelTwo> MyModelTwos { get; set; }
DbSet<MyModelThree> MyModelThrees { get; set; }
int SaveChanges();
// Other methods needed to use the DbContext
}
In one of my ViewModels:
public ConstructorMethod(IEventAggregator eventAggregator, IAppDatabaseContext dbContext) {
_db = dbContext; // I then use this in my Observed Properties
}
We're investigating using RIA Services (July 09 Preview) to expose parts of an existing EF model. We've added a Domain Service class to our web application and specified the EF model to use and selected a few of the entities we wish to make available via the domain service (some have editing enabled, most do not).
We build and everything is great, but if we want to add an additional entity to the domain service how do we do that. Is it a case of delete your current class and re-add and this hole will be plugged when RIA Services hits RTM?
I agree, that's annoying to type in all that manually every time the DB changes. What i end up doing is creating a new temporary domain service classes (and metadata) and cut&pasting the code into the existing domain service and then removing the temp service from the project.
Another option can be (didn't try it) to make the generated file a partial class, put all the new queries into a separate file and every time the DB Schema changes just blow away the generated file and recreate it using the wizard. Just a thought
You can just add the code for the new entities... just add the right methods, query, and depending on which operations you need, insert, update, delete and custom ones.
Yoiu shouldn't have to delete your current class, which theoretically contains a bunch of interesting app logic (I'd imagine) just because you want to add an entity.
My solution to this problem was to create a code snippet that does most of the work.
I only have to type efdsmethods, tab twice, and replace the EntitySet name, EntityType name, and entity variable for the methods to use and then I'm done. It makes adding the 4 standard methods very easy.
I've submitted my snippet as a patch (#10154) to the Silverlight Contrib project on codeplex, but it hasn't been accepted yet. Until then you can download the snippet from here.
Hope this helps you.
I am using LLBL Gen Pro v2.6 and am attempting to create a means of auditing changes made to the database. Now, I know that LLBL Gen has auditing built into it using AuditorBase and dependency injection. The question I have is; I need to track not only the stuff that LLBL Gen exposes as auditable, but also the User who made the changes. From what I've seen there isn't a built in way of gathering this information. Has anyone used LLBL Gen's built in auditing and determined a way to do this?
Wayne E. Pfeffer
I have used LLBLGens Auditing classes. Determining the user is really something that you will have to handle. There are too many variables for LLBLGen to actually do this for you. How are your users handled? Is this a winforms or asp.net application?
The best solution would be to store the UserId in a session variable or static variable depending on which is more appropriate for your application. In your implementation of the Auditing class you can just pull the UserId from its storage place.
Another potential solution would be to override the Entity Class or the Data Adapter classes and pass the UserId in to your save methods. However, this would be a lot more work.
In my WinForms app, I accomplish this by creating a custom IPrincipal and stick that on System.Threading.Thread.CurrentPrincipal when a user logs into the application. Then, I can easily grab that from inside my LLBLGen auditing classes.
We're also about to implement auditing of changes to the db, and have the same issue of adding the user_id to the auditlog. I can see you can do the pull-approach, e.g. fetchingn the user_id from the web session (we're building a web application), but this would completely mess up the layering of the application, as I see it!?
I.e. if the DAL pulls data information from the presentation layer (web session), I won't be able to use the DAL in other contexts?
Best regards,
--thomas