Skip to content

Instantly share code, notes, and snippets.

@sinelaw
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sinelaw/9084984 to your computer and use it in GitHub Desktop.
Save sinelaw/9084984 to your computer and use it in GitHub Desktop.
Super-hacky workaround for missing TVF support in EF code first, using an interceptor to rewrite a table name as a TVF function call
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure.Interception;
using System.Data.Entity.ModelConfiguration;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Shamespace
{
// Example usage - implementation is below the Program class
class Program
{
static void Main(string[] args)
{
var module = new DataExportModule();
module.Initialize(new Keywords());
DbInterception.Add(new TVFInterceptor(new Guid("12345678-1234-1234-1234-123456789012")));
using (var entities = new EntitiesWithSecuredFunction("Entities"))
{
Debug.WriteLine("Count = " + entities.MyTableValuedFunction.Count().ToString());
}
}
}
public class MyTableValuedFunction
{
public int SomeEntityId { get; set; }
}
public class MyTableValuedFunction_Map :EntityTypeConfiguration<MyTableValuedFunction>
{
public MyTableValuedFunction_Map()
{
this.ToTable("MyTableValuedFunction" + TVFInterceptor.TVFSuffix);
this.HasKey(x => x.SomeEntityId);
this.Property(t => t.SomeEntityId).IsRequired().HasColumnName("SomeEntityId");
}
}
public class EntitiesWithSecuredFunction : Entities
{
public EntitiesWithSecuredFunction(string nameOrConnectionString) : base(nameOrConnectionString) { }
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new MyTableValuedFunction_Map());
}
public DbSet<MyTableValuedFunction> MyTableValuedFunction { get; set; }
}
public class TVFInterceptor : System.Data.Entity.Infrastructure.Interception.IDbCommandInterceptor
{
public TVFInterceptor(params object[] parameters)
{
this._parameters = parameters;
}
public const string TVFSuffix = "_TVFInterceptorPrefix_";
private object[] _parameters;
#region IDbCommandInterceptor Members
public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { }
public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { }
public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { }
public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
UpdateCommand(command);
}
public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { }
public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
UpdateCommand(command);
}
#endregion
#region Protected Methods
private void UpdateCommand(DbCommand command)
{
var text = command.CommandText;
var parameters = this._parameters.Select(x => {
var param = command.CreateParameter();
param.Value = x;
command.Parameters.Add(param);
return param;
});
Debug.WriteLine("Original command: ", command.CommandText);
command.CommandText = text.Replace(TVFSuffix + "]", "](" + String.Join(", ", parameters.Select(x => "@" + x.ParameterName)) + ")");
Debug.WriteLine("Modified command: ", command.CommandText);
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment