Can I instruct EF DbContext to use "real" parameter names?

I am using an EF (6 if it matters) subclass DbContext

and trying to implement an interceptor to set or update audit data when an object is written to the database.

My interceptor class:

public class EntitySaveInterceptor : BaseDbCommandInterceptor
{
    private const string CreatedAt = "@CreatedAt";
    private const string ModifiedAt = "@ModifiedAt";

    //called for update, but not insert
    public override void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
        var parameters = command.Parameters
            .OfType<DbParameter>()
            .ToDictionary(p => p.ParameterName, p => p);
        if (parameters.ContainsKey(ModifiedAt))
        {
            parameters[ModifiedAt].Value = SystemTime.UtcNow();
        }
    }

    //called for insert
    public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        var parameters = command.Parameters
            .OfType<DbParameter>()
            .ToDictionary(p => p.ParameterName, p => p);
        if (parameters.ContainsKey(CreatedAt))
        {
            parameters[CreatedAt].Value = SystemTime.UtcNow();
        }
        if (parameters.ContainsKey(ModifiedAt))
        {
            parameters[ModifiedAt].Value = SystemTime.UtcNow();
        }
    }
}

      

The problem I am having is that these commands do not contain parameters "@CreatedAt"

or "@ModifiedAt"

. Instead, the value for the column CreatedAt

is passed by a parameter named @3

(indicating zero indexing in the list of values), and the value for column ModifiedAt

(a DateTime?

) is complex - encoded as NULL

in the generated SQL when its value is NULL

.

I found this answer , but a cursory analysis of the propertySqlCommand

reveals what BindByName

a specific ODP.Net concept is.

Obviously I can check the command text at this point, match the column names in the statement INSERT

with the parameter names and NULL

in the clause, VALUES

and update the collection command.Parameters

to match the new SQL. But, if possible, I would prefer to use parameter names DbContext

that match the column names.

So - can I instruct my, DbContext

or whatever it relies on, to use parameter names based on property or column names when it creates objects DbCommand

?

+3


source to share


1 answer


An alternative would be to override DbContext.SaveChanges

and set property values ​​there. Below is an example of type agnostic (although not necessarily the most efficient) current date / time for any added object with a property CreatedAt

:



    public override int SaveChanges()
    {
        foreach( var entry in this.ChangeTracker.Entries() )
        {
            if( entry.State == EntityState.Added && 
                entry.CurrentValues.PropertyNames.Contains( "CreatedAt" ) )
            {
                entry.CurrentValues[ "CreatedAt" ] = DateTime.Now;
            }
        }

        return base.SaveChanges();
    }

      

+2


source







All Articles