Enterprise Library 5.0 Exception Handler: How to remove sections from error message - enterprise-library

I wrote up a custom MongoDB Listener with Entlib 5.0 as my Exception Handler in my web app. It works great except for the fact that it creates a document entry for every "line" below, including the empty lines:
----------------------------------------
Timestamp: 4/17/2012 4:13:50 PM
Message: HandlingInstanceID: c3c5f58a-89b3-4b64-b05d-3f72f998bab4
An exception of type 'System.NullReferenceException' occurred and was caught.
-----------------------------------------------------------------------------
04/17/2012 16:13:50
Type : System.NullReferenceException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Message : Object reference not set to an instance of an object.
Source : MyCo.Webservices.TheCoolService
Data : System.Collections.ListDictionaryInternal
TargetSite : System.String TestExceptionHandling()
Stack Trace : at Logging.TestExceptionHandling() in C:\tfs\Development\Source\MyCo.Webservices.TheCoolService\Logging\Logging.cs:line 55
----------------------------------------
What I'd like to do is throw most of this information into one document so as to not have 10 different documents for the same error. Even writing my own Exception formattter (http://msdn.microsoft.com/en-us/library/ff664587(v=pandp.50).aspx) I still can't seem to get around the multiple calls to the customlistener.Write() method, each of which creates a new document in my mongodb collection.
My Entlib experience is limited, but I don't see how to get around it unless I write the whole ExceptionFormatter from scratch. Anybody have any ideas how to get around this?

Found my problem. Turns out that I was missing the TraceData() method implementation on my listener. Once I told it what to do there, it handled the error message like a single WriteLine() call.

Related

.NET Entity Framework Core 3.1 - Nlog leaking memory when :format=# when calling update on a big model and a db error occurs

Happens in the save below:
context.Update(myBigObject);
await context.SaveChangesAsync(); -> Hangs here and RAM goes up until all the memory is finished
It only happens when a db error occurs ("String or binary data would be truncated" to be exact, meaning trying to stuff too large string in a field that's too small).
It happens when nlog config is:
${exception:format=#}
One "fix" is to change it to:
${exception:format=toString} -> But then I lose all the inner exception logging
See nlog docs on the difference between :format=# and :format=toString:
https://github.com/NLog/NLog/wiki/Exception-Layout-Renderer
It's happening to more people than me (see bottom comment) and happening in both Serilog and Nlog (so maby it's a EF Core thing):
https://github.com/dotnet/efcore/issues/24663#issuecomment-1349965403
Any idea how to fix without using :format=toString in nlog config?
NLog 4.7 allows you to override the reflection for a specific exception-type (Ex. Microsoft.EntityFrameworkCore.DbUpdateException) like this:
LogManager.Setup().SetupSerialization(s =>
s.RegisterObjectTransformation<Microsoft.EntityFrameworkCore.DbUpdateException>(ex => new {
Type = ex.GetType().ToString(),
Message = ex.Message,
StackTrace = ex.StackTrace,
Source = ex.Source,
InnerException = ex.InnerException,
})
);
See also: https://github.com/NLog/NLog/wiki/How-to-use-structured-logging#customize-object-reflection

Enterprise Library Logging - How can I prevent the "General Information: 0 :" entry?

I'm using EntLib 5.0 Logging Application Block. I created a CustomTraceListener and while testing it I noticed that each time I log with Logger.Write() my listener's Write() method is called with
General Information: 0 :
and then the WriteLine() method is called with the expected and desired log content that the TextFormatter produced
I can't figure out why I'm getting that first "General Information: 0 :" message.
Anyone know if that is controlled somewhere in the config?
While investigating why the TextFormatter wasn't being used I read more about custom TraceListener implementations and learned that you need to override the TraceData method as well:
public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
Once I implemented that method the "General Information" messages stopped happening AND my TextFormatter with it's custom template string was being used. All is well!

Data driven unit test breaking entity framework connection

I have an application that uses entity framework. I am writing a unit test in which I would like to use data driven testing from a CSV file.
However, when I run the test, I get an error that the sqlserver provider cannot be loaded:
Initialization method UnitTest.CalculationTest.MyTestInitialize threw
exception. System.InvalidOperationException:
System.InvalidOperationException: The Entity Framework provider type
'System.Data.Entity.SqlServer.SqlProviderServices,
EntityFramework.SqlServer' registered in the application config file
for the ADO.NET provider with invariant name 'System.Data.SqlClient'
could not be loaded. Make sure that the assembly-qualified name is
used and that the assembly is available to the running application.
If I remove the data driven aspects and just test a single value, then the test works.
If I just use the data driven aspects and remove the Entity Framework stuff, then the test works.
So, its only when I try to use data driven test with entity framework active at the same time do I get the error. So, where am I going wrong here?
Here's my test method:
[TestMethod, TestCategory("Calculations")
, DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV"
, "ConvertedMeanProfileDepth.csv", "ConvertedMeanProfileDepth#csv"
, Microsoft.VisualStudio.TestTools.UnitTesting.DataAccessMethod.Sequential)
, DeploymentItem("ConvertedMeanProfileDepth.csv")]
public void ConvertedMeanProfileDepthTest()
{
ConvertedMeanProfileDepth target = new ConvertedMeanProfileDepth();
Decimal mpd = decimal.Parse(this.TestContext.DataRow["mpd"].ToString());
Decimal expected = decimal.Parse(this.TestContext.DataRow["converted"].ToString());
Decimal actual;
actual = target.Calculate(mpd);
Assert.AreEqual(expected, actual);
}
So I managed to work it out in the end. For future reference, here's the solution:
Rob Lang's post, Entity Framework upgrade to 6 configuration and nuget magic, reminded me of the issue here:
When a type cannot be loaded for a DLL that is referenced in a
project, it usually means that it has not been copied to the output
bin/ directory. When you're not using a type from a referenced
library, it will not be copied.
And this will raise its ugly head the moment you use deployment items in your tests. If you use a deployment item in your test, then all of the required binaries are copied to the deployment directory. Problem is, if you are using dynamically loaded items, then the test suite does not know it has to copy those items.
With Entity Framework, this means that your providers will not be copied to the deployment location and you will receive the error as per my question.
To resolve the issue, simply ensure that your entity framework provider is also marked as a deployment item.
So, note the inclusion of DeploymentItem(#"EntityFramework.SqlServer.dll") in my test attributes. All works perfectly from here:
[TestMethod, TestCategory("Calculations")
, DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV"
, "ConvertedMeanProfileDepth.csv", "ConvertedMeanProfileDepth#csv"
, Microsoft.VisualStudio.TestTools.UnitTesting.DataAccessMethod.Sequential)
, DeploymentItem("ConvertedMeanProfileDepth.csv")
, DeploymentItem(#"EntityFramework.SqlServer.dll")]
public void ConvertedMeanProfileDepthTest()
{
ConvertedMeanProfileDepth target = new ConvertedMeanProfileDepth();
Decimal mpd = decimal.Parse(this.TestContext.DataRow["mpd"].ToString());
Decimal expected = decimal.Parse(this.TestContext.DataRow["converted"].ToString());
Decimal actual;
actual = target.Calculate(mpd);
Assert.AreEqual(expected, actual);
}

F#. How to pass SQLite connection string to EF

I am trying to make SQLite work with EF6 and F3 using System.Data.Sqlite.
I am following walkthrough described here and got edmx file and C# program to compile (I've done that before).
Walkthrough: Generating F# Types from an EDMX Schema File (F#)
Default code shown no errors during the design time and table structure is picked up by VS. Basically, edmx file is ok.
type internal edmx = EdmxFile<"ModelK.edmx">
[<EntryPoint>]
let main argv =
let context = new edmx.MyBaseModel.MyBaseEntities(strBulder)
query { for course in context.T1 do
select course.r1 }
|> Seq.iter (fun course -> printfn "%s" course)
printfn "%A" argv
0 // return an integer exit code
I am using NuGet package System.Data.SQLite EF6 1.0.94.0, deps EntityFramework 6.1.1, System.Data.SQLite Core 1.0.94.0 and have bundle installed from SQLite side (one with VS2013 support).
My problem is sql connecion string. EF requires connection string with meta and the regular sting doesn't work.
This is my original connection string from designer.
#"metadata=res://*/ModelK.csdl|res://*/ModelK.ssdl|res://*/ModelK.msl;provider=System.Data.SQLite.EF6;provider connection string="data source=D:\VS2013\FSharp940\FSharp940MyBase.db"" providerName="System.Data.EntityClient""
What I've tried so far:
Passing escaped (" to make a valid string and some other escape seqs) to MyBaseEntities(strBulder).
System.ArgumentException was unhandled Message: An unhandled exception
of type 'System.ArgumentException' occurred in System.Data.Entity.dll
Additional information: keyword not supported: data source.
Followed some SO advice and replaced " with '.
Got Error reading schema, must start with / and be divided by :.
The type provider
'Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders'
reported an error: Error reading schema. fel 7005: Parametern
source=D:\VS2013\FSharp940\FSharp940\MyBase.db har angetts p† ett
felaktigt s„tt. Alla v„xlar m†ste b”rja med tecknet / och namnet m†ste
avgr„nsas fr†n v„rdet med kolon ':'.
Taken my C# App.Config entity connection strings and other things to my F# App.Config and reading from there.
type internal FooDb =
SqlEntityConnection<ConnectionStringName="MyBaseEntities",
ConfigFile="App.config">
Nope.
The type provider
'Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders'
reported an error: Error reading schema. fel 7005: Parametern
source=D:\VS2013\FSharp940\FSharp940\MyBase.db
I do understand that it is complaining about filepath and done some experiments with it without any results
The type provider
'Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders'
reported an error: Error reading schema. fel 7001: keywork st”ds not:
metadata.
Finally I tried EntityConnectionStringBuilder.
let strBulder =
let conn = new EntityConnectionStringBuilder()
conn.Metadata <- #"res://*/ModelK.csdl|res://*/ModelK.ssdl|res://*/ModelK.msl;"
conn.Provider <- #"System.Data.EntityClient"
conn.ConnectionString <- #"D:\VS2013\FSharp940\FSharp940\MyBase.db"
let ec = new EntityConnection(conn.ToString())
ec
New one...
An unhandled exception of type 'System.TypeInitializationException'
occurred in Unknown Module.
Everything I write to conn.ConnectionString throws an exception, including MyBase.db without any path.
I see that the problem is in connection string and probably my filepath, but at the moment have no idea what the correct format is. I mean... EF must understand it's own config file, right?
Any ideas? :)

GetExportedValues<MyType> returns nothing, I can see the parts

I have a strange MEF problem, I tested this in a test project and it all seems to work pretty well but for some reason not working in the real project
This is the exporting code
public void RegisterComponents()
{
_registrationBuilder = new RegistrationBuilder();
_registrationBuilder
.ForTypesDerivedFrom(typeof(MyType))
.SetCreationPolicy(CreationPolicy.NonShared)
.Export();
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(MyType).Assembly, _registrationBuilder));
var directoryCatalog = new DirectoryCatalog(PathToMyTypeDerived, _registrationBuilder);
catalog.Catalogs.Add(directoryCatalog);
_compositionContainer = new CompositionContainer(catalog);
_compositionContainer.ComposeParts();
var exports = _compositionContainer.GetExportedValues<MyType>();
Console.WriteLine("{0} exports in AppDomain {1}", exports.Count(), AppDomain.CurrentDomain.FriendlyName);
}
exports count is 0 :( Any ideas why?
IN the log file I have many of this
System.ComponentModel.Composition Information: 6 : The ComposablePartDefinition 'SomeOthertype' was ignored because it contains no exports.
Though I would think this is ok because I wasn' interested in exporting 'someOtherType'
UPDATE: I found this link but after debuging over it I am not wiser but maybe I m not following up properly.
Thanks for any pointers
Cheers
I just had the same problem and this article helped me a lot.
It describes different reasons why a resolve can fail. One of the more important ones is that the dependency of a dependency of the type you want to resolve is not registered.
What helped me a lot was the the trace output that gets written to the Output window when you debug your application. It describes exactly the reasons why a type couldn't be resolved.
Even with this output. you might need to dig a little bit, because I only got one level deep.
Example:
I wanted to resolve type A and I got a message like this:
System.ComponentModel.Composition Warning: 1 : The ComposablePartDefinition 'Namespace.A' has been rejected. The composition remains unchanged. The changes were rejected because of the following error(s): The composition produced multiple composition errors, with 1 root causes. The root causes are provided below. Review the CompositionException.Errors property for more detailed information.
1) No exports were found that match the constraint:
ContractName Namespace.IB
RequiredTypeIdentity Namespace.IB
Resulting in: Cannot set import 'Namespace.A..ctor (Parameter="b", ContractName="namespace.IB")' on part 'Namespace A'.
Element: Namespace.A..ctor (Parameter="b", ContractName="Namespace.IB") --> Namespace.A --> AssemblyCatalog (Assembly="assembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=...")
But I clearly saw a part for Namespace.IB. So, in the debugger, I tried to resolve that one. And I got another trace output. This time it told me that my implementation of Namespace.IB couldn't be resolved because for one of its imports there was a missing export, so basically the same message as above, just with different types. And this time, I didn't find a part for that missing import. Now I knew, which type was the real problem and figure out, why no registration happened for it.