EntityFramework 6.0.0-alpha3 - EdmxWriter.WriteEdmx() fails after update to alpha3 from alpha2 - entity-framework

The following extension works for EF6 alpha2 but stopped working with alpha3 with null reference exception. The failing statement is the EdmxWriter.WriteEdmx(..)
The views pre-generation is performed on a code-first context.
How to achieve pre-generate views using EF6 alpha3?
public static PreGeneratedViews PreGenerateViews<T>(this T dbContext) where T : DbContext
{
Trace.TraceInformation("PreGenerating views");
//define ef collections
EdmItemCollection edmItemCollection = null;
StoreItemCollection storeItemCollection = null;
StorageMappingItemCollection mappingItemCollection = null;
//get ef collections
GetItemCollections(
GetEdmx(dbContext),
out edmItemCollection,
out storeItemCollection,
out mappingItemCollection);
IList<EdmSchemaError> errors = null;
//get the generated views
Dictionary<string, string> extentViews = GetExtentViews(mappingItemCollection, out errors);
//return the pregenerated views as string (xml document)
return new PreGeneratedViews
{
EdmEntityContainerName = edmItemCollection.GetItems<EntityContainer>().Single().Name,
StoreEntityContainerName = storeItemCollection.GetItems<EntityContainer>().Single().Name,
HashOverMappingClosure =
ReflectionHelper.GetMappingClosureHash(edmItemCollection.EdmVersion,
mappingItemCollection),
HashOverAllExtentViews =
ReflectionHelper.GenerateHashForAllExtentViewsContent(edmItemCollection.EdmVersion,
extentViews),
ViewCount = extentViews.Count,
Views = CreateViews(extentViews),
ViewsEmbeddedResourceName =
string.Format("DbContextViews{0}.xml", Guid.NewGuid().ToString("N")),
};
}
private static XDocument GetEdmx(DbContext dbContext)
{
var ms = new MemoryStream();
using (XmlWriter writer = XmlWriter.Create(ms))
{
EdmxWriter.WriteEdmx(dbContext, writer);
}
ms.Position = 0;
return XDocument.Load(ms);
}
private static void SplitEdmx(XDocument edmx, out XmlReader csdlReader, out XmlReader ssdlReader,
out XmlReader mslReader)
{
// xml namespace agnostic to make it work with any version of Entity Framework
XNamespace edmxNs = edmx.Root.Name.Namespace;
XElement storageModels = edmx.Descendants(edmxNs + "StorageModels").Single();
XElement conceptualModels = edmx.Descendants(edmxNs + "ConceptualModels").Single();
XElement mappings = edmx.Descendants(edmxNs + "Mappings").Single();
ssdlReader = storageModels.Elements().Single(e => e.Name.LocalName == "Schema").CreateReader();
csdlReader = conceptualModels.Elements().Single(e => e.Name.LocalName == "Schema").CreateReader();
mslReader = mappings.Elements().Single(e => e.Name.LocalName == "Mapping").CreateReader();
}
private static void GetItemCollections(XDocument edmx, out EdmItemCollection edmItemCollection,
out StoreItemCollection storeItemCollection,
out StorageMappingItemCollection mappingItemCollection)
{
// extract csdl, ssdl and msl artifacts from the Edmx
XmlReader csdlReader, ssdlReader, mslReader;
SplitEdmx(edmx, out csdlReader, out ssdlReader, out mslReader);
// Initialize item collections
edmItemCollection = new EdmItemCollection(new[] {csdlReader});
storeItemCollection = new StoreItemCollection(new[] {ssdlReader});
mappingItemCollection = new StorageMappingItemCollection(edmItemCollection, storeItemCollection,
new[] {mslReader});
}
private static Dictionary<string, string> GetExtentViews(StorageMappingItemCollection mappingItemCollection,
out IList<EdmSchemaError> errors)
{
Dictionary<EntitySetBase, string> views = ReflectionHelper.GenerateViews(mappingItemCollection, out errors);
if (errors != null && errors.Any())
{
return null;
}
var extentViews = new Dictionary<string, string>(views.Count);
foreach (var kvp in views)
{
extentViews.Add(
GetExtentFullName(kvp.Key),
kvp.Value.Replace("\r\n", "\n")); // replace accounts for Xml new line normalization
}
return extentViews;
}
private static string GetExtentFullName(EntitySetBase entitySet)
{
return string.Format("{0}.{1}", entitySet.EntityContainer.Name, entitySet.Name);
}
private static string CreateViews(Dictionary<string, string> extentViews)
{
var sb = new StringBuilder();
//var embeddedViewsFileName = Path.ChangeExtension(Host.TemplateFile, "xml");
using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings
{
Indent = true,
Encoding = Encoding.UTF8
}))
{
writer.WriteStartElement("views");
foreach (var kvp in extentViews)
{
writer.WriteStartElement("view");
writer.WriteAttributeString("extent", kvp.Key);
writer.WriteCData(kvp.Value);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
return sb.ToString();
}
#region Nested type: ReflectionHelper
private static class ReflectionHelper
{
private static readonly Assembly efAssembly = typeof (StorageMappingItemCollection).Assembly;
private static readonly MethodInfo generateViewsMethodInfo =
typeof (StorageMappingItemCollection).GetMethod("GenerateEntitySetViews",
BindingFlags.NonPublic | BindingFlags.Instance);
private static readonly MethodInfo getMappingClosureHashMethodInfo =
efAssembly.GetType("System.Data.Entity.Core.Mapping.MetadataMappingHasherVisitor", true)
.GetMethod("GetMappingClosureHash", BindingFlags.Static | BindingFlags.NonPublic);
private static readonly MethodInfo generateHashForAllExtentViewsContentMethodInfo =
efAssembly.GetType("System.Data.Entity.Core.Common.Utils.MetadataHelper", true)
.GetMethod("GenerateHashForAllExtentViewsContent", BindingFlags.Static | BindingFlags.NonPublic);
public static Dictionary<EntitySetBase, string> GenerateViews(
StorageMappingItemCollection mappingItemCollection, out IList<EdmSchemaError> errors)
{
errors = null;
return
(Dictionary<EntitySetBase, string>)
generateViewsMethodInfo.Invoke(mappingItemCollection, new object[] {errors});
}
public static string GetMappingClosureHash(double schemaVersion,
StorageMappingItemCollection mappingItemCollection)
{
return (string) getMappingClosureHashMethodInfo.Invoke(
null,
new object[]
{
schemaVersion,
// CodeFirst currently creates always one entity container
mappingItemCollection.GetItems<GlobalItem>().Single(
i => i.GetType().Name == "StorageEntityContainerMapping")
});
}
public static string GenerateHashForAllExtentViewsContent(double schemaVersion,
Dictionary<string, string> extentViews)
{
return (string) generateHashForAllExtentViewsContentMethodInfo.Invoke(
null,
new object[] {schemaVersion, extentViews});
}
}
The stacktrace is the following:
NullReferenceException
at: System.Data.Entity.Edm.Serialization.EdmSerializationVisitor.VisitEdmAssociationSet(AssociationSet item)
at: System.Data.Entity.Edm.EdmModelVisitor.VisitCollection[T](IEnumerable1 collection, Action1 visitMethod)
at: System.Data.Entity.Edm.EdmModelVisitor.VisitAssociationSets(EntityContainer container, IEnumerable`1 associationSets)
at: System.Data.Entity.Edm.EdmModelVisitor.VisitEdmEntityContainer(EntityContainer item)
at: System.Data.Entity.Edm.Serialization.EdmSerializationVisitor.VisitEdmEntityContainer(EntityContainer item)
at: System.Data.Entity.Edm.EdmModelVisitor.VisitCollection[T](IEnumerable1 collection, Action1 visitMethod)
at: System.Data.Entity.Edm.EdmModelVisitor.VisitEntityContainers(IEnumerable`1 entityContainers)
at: System.Data.Entity.Edm.EdmModelVisitor.VisitEdmModel(EdmModel item)
at: System.Data.Entity.Edm.Serialization.EdmSerializationVisitor.Visit(EdmModel edmModel, String namespaceName, String provider, String providerManifestToken)
at: System.Data.Entity.Edm.Serialization.EdmSerializationVisitor.Visit(EdmModel edmModel, String provider, String providerManifestToken)
at: System.Data.Entity.Edm.Serialization.SsdlSerializer.Serialize(EdmModel dbDatabase, String provider, String providerManifestToken, XmlWriter xmlWriter, Boolean serializeDefaultNullability)
at: System.Data.Entity.ModelConfiguration.Edm.Serialization.EdmxSerializer.WriteEdmxRuntime()
at: System.Data.Entity.ModelConfiguration.Edm.Serialization.EdmxSerializer.Serialize(DbDatabaseMapping databaseMapping, DbProviderInfo providerInfo, XmlWriter xmlWriter)
at: System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbModel model, XmlWriter writer)
at: System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer)
at: **.DbContextPreGenerateViewExtension.GetEdmx(DbContext dbContext)
Thanks!

I just submitted a fix for work item 867 (35852e8392ad). It should fix the NRE. The fix should be included in the today's nightly build. Can you give it a try and let me know if this fixed the problem?

This is a known bug in Alpha 3.

Related

Clean up process throws an exception (itextsharp)

I get an exception when trying to cleanup a section of a PDF (text searchable). It only happens on some PDFs. I noticed the difference is the text might be a little bit skewed.
I create some annotations of the PDF. Save it to file, then use the cleanup procedure. It works like a charm on most of the PDFs.
(itextsharp: 5.5.13.0)
Thanks in advance.
at System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement, Boolean validateImageData)
at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpRenderListener.ProcessImage(Byte[] imageBytes, IList`1 areasToBeCleaned)
at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpRenderListener.RenderImage(ImageRenderInfo renderInfo)
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.ImageXObjectDoHandler.HandleXObject(PdfContentStreamProcessor processor, PdfStream xobjectStream, PdfIndirectReference refi, ICollection markedContentInfoStack)
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.DisplayXObject(PdfName xobjectName)
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.Do.Invoke(PdfContentStreamProcessor processor, PdfLiteral oper, List`1 operands)
at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpContentOperator.Invoke(PdfContentStreamProcessor pdfContentStreamProcessor, PdfLiteral oper, List`1 operands)
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.InvokeOperator(PdfLiteral oper, List`1 operands)
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.ProcessContent(Byte[] contentBytes, PdfDictionary resources)
at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpProcessor.CleanUpPage(Int32 pageNum, IList`1 cleanUpLocations)
at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpProcessor.CleanUp()
at AU.PDF.Redaction.PdfProcessor.Redact(String inputFilePath, String outputFilePath, IEnumerable`1 options) in C:\Users\Depen585\Documents\POC\Redaction\AU.PDF.Redaction\PdfProcessor.cs:line 123
at Poc.Program.Main(String[] args) in C:\Users\Depen585\Documents\POC\Redaction\Poc\Program.cs:line 91
UPDATE
Bruno, using your method I get this error now (works with some, fails with others):
at iText.PdfCleanup.PdfCleanUpFilter.FilterImage(ImageRenderInfo image, IList`1 imageAreasToBeCleaned)
at iText.PdfCleanup.PdfCleanUpFilter.FilterImage(FilteredImageKey imageKey)
at iText.PdfCleanup.PdfCleanUpProcessor.CheckIfImageAndClean(IList`1 operands)
at iText.PdfCleanup.PdfCleanUpProcessor.FilterContent(String operator, IList`1 operands)
at iText.PdfCleanup.PdfCleanUpProcessor.InvokeOperator(PdfLiteral operator, IList`1 operands)
at iText.Kernel.Pdf.Canvas.Parser.PdfCanvasProcessor.ProcessContent(Byte[] contentBytes, PdfResources resources)
at iText.PdfCleanup.PdfCleanUpProcessor.ProcessContent(Byte[] contentBytes, PdfResources resources)
at iText.Kernel.Pdf.Canvas.Parser.PdfCanvasProcessor.ProcessPageContent(PdfPage page)
at iText.PdfCleanup.PdfCleanUpProcessor.ProcessPageContent(PdfPage page)
at iText.PdfCleanup.PdfCleanUpTool.CleanUpPage(Int32 pageNumber, IList`1 cleanUpLocations)
at iText.PdfCleanup.PdfCleanUpTool.CleanUp()
at AU.PDF.PdfProcessor.Redact(String inputFilePath, String outputFilePath, String textToRedact) in C:\Users\Depen585\Documents\POC\Redaction\AU.PDF\PdfProcessor.cs:line 38
at Poc.Program.Main(String[] args) in C:\Users\Depen585\Documents\POC\Redaction\Poc\Program.cs:line 91
Here is the code:
public class PdfProcessor
{
public void Initialize(string licenseKeyFilePath)
{
if (string.IsNullOrEmpty(licenseKeyFilePath)) throw new ArgumentNullException(nameof(licenseKeyFilePath));
LicenseKey.LoadLicenseFile(licenseKeyFilePath);
}
public void Redact(string inputFilePath, string outputFilePath, string textToRedact)
{
if (string.IsNullOrEmpty(inputFilePath)) throw new ArgumentNullException(nameof(inputFilePath));
if (string.IsNullOrEmpty(outputFilePath)) throw new ArgumentNullException(nameof(outputFilePath));
if (string.IsNullOrEmpty(textToRedact)) throw new ArgumentNullException(nameof(textToRedact));
//CompositeLocationExtractionStrategy strategy = new CompositeLocationExtractionStrategy();
//strategy.add(new PatternLocationExtractionStrategy(textToRedact).setRedactionColor(Color.PINK));
using (PdfReader reader = new PdfReader(inputFilePath))
using (PdfWriter writer = new PdfWriter(outputFilePath))
using (PdfDocument pdf = new PdfDocument(reader, writer))
{
List<PdfCleanUpLocation> cleanUpLocations = new List<PdfCleanUpLocation>
{
new PdfCleanUpLocation(1, new Rectangle(97, 405, 383, 40), iText.Kernel.Colors.ColorConstants.BLACK)
};
new PdfCleanUpTool(pdf, cleanUpLocations).CleanUp();
//PdfAutoSweep autoSweep = new PdfAutoSweep(composite);
//autoSweep.CleanUp(pdf);
}
}
}
UPDATE 2:
Even with custom strategy (RegexBasedLocationExtractionStrategy) it fails on the same PDFS. See below...
public class RegexLocationExtractionStrategy : RegexBasedLocationExtractionStrategy, ICleanupStrategy
{
private readonly string Regex;
public RegexLocationExtractionStrategy(string regex) : base(regex)
{
Regex = regex ?? throw new ArgumentNullException(nameof(regex));
}
public Color GetRedactionColor(IPdfTextLocation location)
{
return ColorConstants.BLACK;
}
public ICleanupStrategy Reset()
{
return new RegexLocationExtractionStrategy(Regex);
}
}
public class PdfProcessor
{
public void Initialize(string licenseKeyFilePath)
{
if (string.IsNullOrEmpty(licenseKeyFilePath)) throw new ArgumentNullException(nameof(licenseKeyFilePath));
LicenseKey.LoadLicenseFile(licenseKeyFilePath);
}
public void Redact(string inputFilePath, string outputFilePath, string regex)
{
if (string.IsNullOrEmpty(inputFilePath)) throw new ArgumentNullException(nameof(inputFilePath));
if (string.IsNullOrEmpty(outputFilePath)) throw new ArgumentNullException(nameof(outputFilePath));
if (string.IsNullOrEmpty(regex)) throw new ArgumentNullException(nameof(regex));
using (PdfReader reader = new PdfReader(inputFilePath))
using (PdfWriter writer = new PdfWriter(outputFilePath))
using (PdfDocument pdf = new PdfDocument(reader, writer))
{
var strategy = new RegexLocationExtractionStrategy(regex);
PdfAutoSweep autoSweep = new PdfAutoSweep(strategy);
autoSweep.CleanUp(pdf);
}
}
}
UPDATE 3:
I can see the redaction annotations when I use the tentative cleanup. Then I pass the clean up locations to the redaction routine and it fails all the same. See below.
public IEnumerable<PdfCleanUpLocation> Annotate(string inputFilePath, string outputFilePath, string regex)
{
if (string.IsNullOrEmpty(inputFilePath)) throw new ArgumentNullException(nameof(inputFilePath));
if (string.IsNullOrEmpty(outputFilePath)) throw new ArgumentNullException(nameof(outputFilePath));
if (string.IsNullOrEmpty(regex)) throw new ArgumentNullException(nameof(regex));
using (PdfReader reader = new PdfReader(inputFilePath))
using (PdfWriter writer = new PdfWriter(outputFilePath))
using (PdfDocument pdf = new PdfDocument(reader, writer))
{
var strategy = new RegexLocationExtractionStrategy(regex);
var autoSweep = new PdfAutoSweep(strategy);
autoSweep.TentativeCleanUp(pdf);
return autoSweep.GetPdfCleanUpLocations(pdf);
}
}
public void Redact(string inputFilePath, string outputFilePath, IEnumerable<PdfCleanUpLocation> locations)
{
if (string.IsNullOrEmpty(inputFilePath)) throw new ArgumentNullException(nameof(inputFilePath));
if (string.IsNullOrEmpty(outputFilePath)) throw new ArgumentNullException(nameof(outputFilePath));
if (locations == null) throw new ArgumentNullException(nameof(locations));
using (PdfReader reader = new PdfReader(inputFilePath))
using (PdfWriter writer = new PdfWriter(outputFilePath))
using (PdfDocument pdf = new PdfDocument(reader, writer))
{
var cleanUpTool = new PdfCleanUpTool(pdf);
locations
.ToList()
.ForEach(location => cleanUpTool.AddCleanupLocation(location));
cleanUpTool.CleanUp();
}
}

CQ5 multifield configuration service

I'm trying to create a CQ5 service with a multifield configuration interface. It would be something like this but at the click of PLUS button it would add not just a new row but a group of N rows.
Property
Field1 +-
Field2
....
FieldN
Any advice?
As far as I know there is no such possibility in the Apache Felix.
Depending on your actual requirement I would consider decomposing the configuration. Try moving all the fieldsets (groups of fields that you'd like to add through the plus button) into a separated configuration. So, closely to the slf4j.Logger configuration you would have a Configuration Factory approach.
A simple configuration factory can look like following
#Component(immediate = true, configurationFactory = true, metatype = true, policy = ConfigurationPolicy.OPTIONAL, name = "com.foo.bar.MyConfigurationProvider", label = "Multiple Configuration Provider")
#Service(serviceFactory = false, value = { MyConfigurationProvider.class })
#Properties({
#Property(name = "propertyA", label = "Value for property A"),
#Property(name = "propertyB", label = "Value for property B") })
public class MyConfigurationProvider {
private String propertyA;
private String propertyB;
#Activate
protected void activate(final Map<String, Object> properties, final ComponentContext componentContext) {
propertyA = PropertiesUtil.toStringArray(properties.get("propertyA"), defaultValue);
propertyB = PropertiesUtil.toStringArray(properties.get("propertyB"), defaultValue);
}
}
Using it is as simple as adding a reference in any #Component
#Reference(cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, referenceInterface = MyConfigurationProvider.class, policy = ReferencePolicy.DYNAMIC)
private final List<MyConfigurationProvider> providers = new LinkedList<MyConfigurationProvider>();
protected void bindProviders(MyConfigurationProvider provider) {
providers.add(provider);
}
protected void unbindProviders(MyConfigurationProvider provider) {
providers.remove(provider);
}
This is one way of doing it.
#Component(label = "My Service", metatype = true, immediate = true)
#Service(MyService.class)
#Properties({
#Property(name = "my.property", description = "Provide details Eg: url=http://www.google.com|size=10|path=/content/project", value = "", unbounded = PropertyUnbounded.ARRAY) })
public class MyService {
private String[] myPropertyDetails;
#Activate
protected void activate(ComponentContext ctx) {
this.myPropertyDetails = getPropertyAsArray(ctx.getProperties().get("my.property"));
try {
if (null != myPropertyDetails && myPropertyDetails.length > 0) {
for(String myPropertyDetail : myPropertyDetails) {
Map<String, String> map = new HashMap<String, String>();
String[] propertyDetails = myPropertyDetails.split("|");
for (String keyValuePair : propertyDetails) {
String[] keyValue = keyValuePair.split("=");
if (null != keyValue && keyValue.length > 1) {
map.put(keyValue[0], keyValue[1]);
}
}
/* the map now has all the properties in the form of key value pairs for single field
use this for logic execution. when there are no multiple properties in the row,
you can skip the logic to split and add in the map */
}
}
} catch (Exception e) {
log.error( "Exception ", e.getMessage());
}
}
private String[] getPropertyAsArray(Object obj) {
String[] paths = { "" };
if (obj != null) {
if (obj instanceof String[]) {
paths = (String[]) obj;
} else {
paths = new String[1];
paths[0] = (String) obj;
}
}
return paths;
}
}

org.hibernate.search.bridge.BridgeException: Exception while calling bridge#objectToString

I am able to insert record and able index them but i am facing an exception while searching
org.hibernate.search.bridge.BridgeException: Exception while calling bridge#objectToString
class: com.edoors.formBean.Hib_cons_Cv
path: cons_cv
I am able search on all coulmn of table except blob column
Field Bridge
public class ByteArrayBridge implements TwoWayStringBridge {
public String objectToString(Object object) {
byte[] data = (byte[]) object;
StringWriter writer = new StringWriter();
InputStream is = null;
try {
is = new ByteArrayInputStream(data);
new AutoDetectParser().parse(is,new WriteOutContentHandler(writer),new Metadata(),new
ParseContext());
return is.toString();
} catch (Exception e) {
System.out.println("Exception "+e);
}
return writer.toString();
}
public Object stringToObject(String string) {
byte[] data=string.getBytes();
Object obj=data;
return obj;
}
}
DAO Class ::
public List searchConsultantByTitle(String jobtitle)
{
List list=null;
Session session = hiberUtil.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
FullTextSession fullTextSession = Search.getFullTextSession(session);
QueryBuilder queryBuilder =
fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Hib_cons_Cv.class).get();
org.apache.lucene.search.Query luceneQuery = null;
luceneQuery =
queryBuilder.keyword().fuzzy().withThreshold(0.7f).onField("cons_cv").matching(jobtitle).createQuery();
FullTextQuery hibernateQuery = fullTextSession.createFullTextQuery(luceneQuery, Hib_cons_Cv.class);
int resultSize = hibernateQuery.getResultSize();
System.out.println(".....resultSize..............................."+resultSize);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
POJO Class
#Entity
#AnalyzerDef(name = "customanalyzer", tokenizer = #TokenizerDef(factory =
KeywordTokenizerFactory.class), filters = {
#TokenFilterDef(factory = LowerCaseFilterFactory.class),
#TokenFilterDef(factory = SnowballPorterFilterFactory.class, params = {
#Parameter(name = "language", value = "English") }) })
#Indexed
public class Hib_cons_Cv {
#Column(name = "cons_cv", unique = false, nullable = false, length = 59296)
#Lob
#Field(analyze = Analyze.NO, store = Store.YES)
#FieldBridge(impl = ByteArrayBridge.class)
private Blob cons_cv;
//setters and getters
}
I also got this error (with no stack trace). Turned out i put in the wrong field name. It was actually using a field with no bridging.

Proper way to profile a DbContext using MiniProfiler and EF 5 and Autofac

The MiniProfiler site gives the following code for generating an Entity Framework ObjectContext:
public static MyModel Get()
{
var conn = new StackExchange.Profiling.Data.EFProfiledDbConnection(GetConnection(), MiniProfiler.Current);
return ObjectContextUtils.CreateObjectContext<MyModel>(conn); // resides in the MiniProfiler.EF nuget pack
}
However, using Entity Framework 5, I am not using an ObjectContext - rather I am using a DbContext. I cannot plug the model name in here, since the CreateObjectContext<T>() method expects T to be of type ObjectContext. (For the same reason, the code given in this answer also doesn't work).
Additionally, I am using autofac to initialize my Db connections. This is being registered with the following (MyData = the name of my EF DataContext):
Builder.RegisterType<MyData>().As<DbContext>().InstancePerHttpRequest();
So combining two parts: how can I use autofac to initialize my DbContext tied into MiniProfiler.EF? And if that is not possible, at least how can I do the first part (create a factory method for MiniProfiler.EF to return a DbContext)?
I just got this working:
public static class DbContextUtils
{
private const BindingFlags PrivateInstance = BindingFlags.NonPublic | BindingFlags.Instance;
public static T CreateDbContext<T>() where T : DbContext
{
return CreateDbContext<T>(GetProfiledConnection<T>());
}
public static T CreateDbContext<T>(this DbConnection connection) where T : DbContext
{
var workspace = new MetadataWorkspace(new[] { "res://*/" }, new[] { typeof(T).Assembly });
var factory = DbProviderServices.GetProviderFactory(connection);
var itemCollection = workspace.GetItemCollection(DataSpace.SSpace);
var providerFactoryField = itemCollection.GetType().GetField("_providerFactory", PrivateInstance);
if (providerFactoryField != null) providerFactoryField.SetValue(itemCollection, factory);
var ec = new EntityConnection(workspace, connection);
return CtorCache<T, DbConnection>.Ctor(ec);
}
public static DbConnection GetProfiledConnection<T>() where T : DbContext
{
var dbConnection = ObjectContextUtils.GetStoreConnection("name=" + typeof(T).Name);
return new EFProfiledDbConnection(dbConnection, MiniProfiler.Current);
}
internal static class CtorCache<TType, TArg> where TType : class
{
public static readonly Func<TArg, TType> Ctor;
static CtorCache()
{
var argTypes = new[] { typeof(TArg) };
var ctor = typeof(TType).GetConstructor(argTypes);
if (ctor == null)
{
Ctor = x => { throw new InvalidOperationException("No suitable constructor defined"); };
}
else
{
var dm = new DynamicMethod("ctor", typeof(TType), argTypes);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Ret);
Ctor = (Func<TArg, TType>)dm.CreateDelegate(typeof(Func<TArg, TType>));
}
}
}
}
It is based on the code in MiniProfiler's ObjectContextUtils.
You use it like this:
builder.Register(c => DbContextUtils.CreateDbContext<MyData>()).As<DbContext>().InstancePerHttpRequest();
This solution REQUIRES your DbContext to have a constructor which takes a DbConnection and passes it to base, like this:
public MyData(DbConnection connection)
: base(connection, true)
{
}
There is a constructor of the DbContext class which takes an existing DbConnection
So you need a new contructor on your MyData which just calls the base
public class MyData : DbContext
{
public MyData(DbConnection existingConnection, bool contextOwnsConnection)
: base(existingConnection, contextOwnsConnection)
{
}
//..
}
Then you register your MyData with Register:
builder.Register(c =>
{
var conn = new EFProfiledDbConnection(GetConnection(), MiniProfiler.Current);
return new MyData(conn, true);
}).As<DbContext>().InstancePerHttpRequest();

StackoverflowException while using SqlDependencies with Ef Framework

I would like to get some feedback about using SqlDependencies with EF Framework 4.0. I have currently implemented a scenario using ObjectQuery in combination with toStraceString() to generate SqlDependency.
Im getting a StackoverflowException somewhere in Entity Framework source code when doing refresh store wins. I thought this error would somewhere in my code, but i cannot find it.
I made up a small example of what i want to do:
public partial class MainWindow : Window
{
private SqlDependency _sqldep;
public delegate void DataChanged(string test);
TestEntities m = new TestEntities();
SqlCommand _cmd;
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
//m.Connection.Open();
SqlDependency.Start(((System.Data.EntityClient.EntityConnection)m.Connection).StoreConnection.ConnectionString);
var query = m.User.AsQueryable<User>();
string query_str = m.User.ToTraceString();
SqlConnection con = new SqlConnection(((System.Data.EntityClient.EntityConnection)m.Connection).StoreConnection.ConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand(query_str, con);
_cmd = cmd;
_sqldep = new SqlDependency(cmd);
_sqldep.OnChange += dependency_OnChange;
cmd.ExecuteReader();
this.Users = m.User;
}
SqlDependency dependency;
// Bei Ă„nderung am gegebenen SQL-Statement
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
dependency = (SqlDependency)sender;
dependency.OnChange -= dependency_OnChange;
NotifierOnDataChanged(string.Empty);
dependency.OnChange += dependency_OnChange;
}
private void NotifierOnDataChanged(string bla)
{
try
{
m.Refresh(System.Data.Objects.RefreshMode.StoreWins, m.User);
}
catch (System.Exception ex)
{
System.Windows.MessageBox.Show(ex.Message, "Fehler");
}
}
private IEnumerable<User> _users;
public IEnumerable<User> Users
{
get { return _users; }
set { _users = value; }
}
}
I'm getting my StackoverflowException at NotifierOnDataChanged -> Refresh