Here is what Sonar is saying:
EnsureLocalDisposalRule Open Updated: 6 days Technical debt: 1 hours
Local 'da' of type 'SqlDataAdapter' is not guaranteed to be disposed of.
Here is the code:
conn1.Open()
Using da As New SqlDataAdapter(qry, conn1)
'fill data set 1 for combobox
da.Fill(ds1)
End Using
ds1.Dispose()
With CompanyCbx
'what the user sees
.DisplayMember = "CMPNY_NM"
'value behind each display member
.ValueMember = "CMPNY_SEQ_ID"
.DataSource = ds1.Tables(0)
.SelectedIndex = 0
End With
'close connection
conn1.Close()
'Dispose connection
conn1.Dispose()
The documentation regarding the Using block states that it disposes of whatever it is 'using,' so I don't understand the error.
Here is Sonar's documentation:
EnsureLocalDisposalRule
This rule checks that disposable locals are always disposed of before the method returns. Use a 'using' statement (or a try/finally block) to guarantee local disposal even in the event an unhandled exception occurs.
Link to the official Mono Gendarme documentation
I would guess that this is just a bug in Sonar's analysis. C# and VB.Net generate slightly different IL for logically the same using code and this difference often throws off decompilers. Generally they are tuned for C# code and miss the subtle difference in VB.Net and hence believe it to be a manual try / finally instead of using
The key difference is that the VB.Net null check in the finally is more complex than the C# one.
C#
IL_000b: ldloc.0
IL_000c: ldnull
IL_000d: ceq
IL_000f: stloc.1
IL_0010: ldloc.1
IL_0011: brtrue.s IL_001a
VB.Net
IL_000c: ldloc.0
IL_000d: ldnull
IL_000e: ceq
IL_0010: ldc.i4.0
IL_0011: ceq
IL_0013: stloc.1
IL_0014: ldloc.1
IL_0015: brfalse.s IL_001e
C# essentially takes the result of ceq and branches on that while VB.Net takes the result, inverts it and then branches on false. Functionally it does the same but the subtle difference often throws off code analysis
Related
My purpose is to add two buttons which allow the user to jump to the first of to the last item quickly. I'm using MVVM path and the code is very simple:
Sub ScrollDown()
If ResponseModel.Items.Count > 0 And ResponseModel.IsDataLoaded Then
If ResponseModel.Items.LastOrDefault IsNot Nothing Then ResponseList.ScrollTo(ResponseModel.Items.LastOrDefault())
End If
End Sub
Sometimes this code throws a NullReferenceException on the last line, yes, the one with End Sub. None of these object are null, so I can't find out what the problem is.
System.NullReferenceException: Object reference not set to an instance of an object. at Microsoft.Phone.Controls.LongListSelector.ScrollTo(Object item, Nullable`1 isGroup) at Microsoft.Phone.Controls.LongListSelector.ScrollTo(Object item) at WindowsPhoneAnswers.Thread.Lambda$_68() at WindowsPhoneAnswers.Thread.Lambda$_67(Object a0, EventArgs a1) at MS.Internal.CoreInvokeHandler.InvokeEventHandler(Int32 typeIndex, Delegate handlerDelegate, Object sender, Object args) at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)
The only possible explanation is that the last item hasn't been realized yet, but how to check it?
The solution sounds weird as well. It seems that calling the method using the Dispatcher solves the issue.
However this is odd since the exception was raised randomly and I'm not on a background thread.
Let us assume the following CIL program:
.assembly extern mscorlib {}
.assembly Program {}
.method private static void Main() cil managed
{
.entrypoint
.maxstack 4
.locals init ( int32[] a,
uint32 t )
// Creates an array of int of size 10
ldc.i4 10
newarr int32
stloc.0
// Writes 0xaabbccdd at the index 2 of the array
ldloc.0
ldc.i4.2
ldc.i4 0xaabbccdd
stelem.i4
// Loads
ldloc.0
ldc.i4 9 // <HERE>
ldelem.i1
stloc.1
ldstr "Value: 0x{0:x8}"
ldloc.1
box [mscorlib]System.UInt32
call void [mscorlib]System.Console::WriteLine(string, object)
ret
}
This program:
creates an array of int size 10
writes 0xaabbccdd at index 2 of the array
tries to read one byte in the array using ldelem.i1
prints the result
The trick is that I use "ldelem.i1" instead of the more standard "idelem.i4" for performance issues (I want to avoid doing masking) The idea is to access to the data of the array the way one does with pointers in C.
But things are not so nice because the program crashes (IndexOutOfRangeException) for indexes of more than 10 as argument for ldelem.i1.
This males the trick useless as I can't access data after the first half of the integer at the third index.
Ideally, I want to access bytes up to index 39, which corresponds to the last byte of the integer at index 9.
I would very much appreciate if somebody had some ideas on this point.
Interesting. The ECMA-335 states that it will throw an exception if the index is greater than or equal to the size of the array, which it definitely is. What surprises me about this isn't that the exception is thrown, but that the index is treated as a byte index into an int array in the first place - I can't see that that's specified anywhere.
I suspect you're into the realms of unspecified behaviour, quite possibly behaviour which isn't intended to be specified - I suspect you're just not meant to use ldelem.i1 on an int array.
I'm generating output for a .Net executable from my own language... the opcode (called 'Random') that's being translated from my language is supposed to create a random number within a specific range.
The goal for my code is to produce the random number using System.Reflection.Emit.ILGenerator class... to understand how the CIL code looks I've created some vb.net code:
Sub Main()
Dim A As Random
A = New Random
Console.WriteLine(A.Next(100))
End Sub
Which ILDASM reports as:
.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 23 (0x17)
.maxstack 2
.locals init ([0] class [mscorlib]System.Random A)
IL_0000: nop
IL_0001: newobj instance void [mscorlib]System.Random::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.s 100
IL_000a: callvirt instance int32 [mscorlib]System.Random::Next(int32)
IL_000f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0014: nop
IL_0015: nop
IL_0016: ret
} // end of method Main::Main
I can reproduce everything using the ILGenerator.Emit method; except the line IL_0001 ("newobj instance void [mscorlib]System.Random::.ctor()")...
Hopefully I haven't overwhelmed anyone with too much information. But I figure it's better to be verbose when describing a problem that seems complex to me.
Finally I have the code that I've produced so far:
Sub EmitRandom()
Dim NewRandom As New Random
Dim stringtype As Type = GetType(System.Random)
Dim paramtypes() As Type = {GetType(Integer)}, blankparams() As Type = {}
'Dim RandomMethod = stringtype.GetMethod("New", paramtypes)
m_ILGen.Emit(OpCodes.Newobj, New Random().GetType)
EmitStoreInLocal(tempVariableRnd)
EmitLoadLocal(tempVariableRnd)
m_ILGen.Emit(OpCodes.Callvirt, stringtype.GetMethod("Next", paramtypes))
End Sub
Which emits the following code:
.
.
.
IL_0073: newobj [mscorlib]System.Random
IL_0078: stloc.2
IL_0079: ldloc.2
IL_007a: callvirt instance int32 [mscorlib]System.Random::Next(int32)
.
.
.
Things that I've tried already:
Coming up with a way to point IL_Gen.Emit(OpCodes.NewObj, ... ctor())... can't figure out how.
Coming up with a way to point to New() - since that seems to be what .ctor() is... New can't be used as anything but an initializer.
Just disabling the Random function until I can come up with a better way of emitting.
The problem seems hard to me but I know there's someone out there who understands code generation and MSIL more easily than I do and who is willing to point out an answer.
Thanks for your time,
Dominick
You need to use the ConstructorInfo:
m_ILGen.Emit(OpCodes.Newobj, GetType(Random).GetConstructor(Type.EmptyTypes))
Also - the storing and loading from local are unnecessary. You really just want the equivalent of new Random().Next(100), right?...in which case storing and loading from a local never happens.
I've a MS SQL 2008 database which is accessed through LINQ for data update/retrival.
My linq is accessed by WCF services in a PerCall instantiation mode for an heavy application. This application has several thread which makes calls to the service, and several application are running in the sametime.
I've often some EntityException happening:
System.Data.EntityException was caught
Message=An error occurred while starting a transaction on the provider connection. See the inner exception for details.
Source=System.Data.Entity
StackTrace:
at System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)
at System.Data.EntityClient.EntityConnection.BeginTransaction()
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
at Infoteam.GfK.TOMServer.DataServer.DataServer.SaveChanges() in D:\Workspace\XYZWASDF\DataServer\DataServer.cs:line 123
InnerException: System.Data.SqlClient.SqlException
Message=Une nouvelle transaction n'est pas autorisée parce que d'autres threads sont en cours d'exécution dans la session.
Source=.Net SqlClient Data Provider
ErrorCode=-2146232060
Class=16
LineNumber=1
Number=3988
Procedure=""
Server=ift-srv114
State=1
StackTrace:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso, String transactionName)
at System.Data.SqlClient.SqlInternalConnection.BeginTransaction(IsolationLevel iso)
at System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel isolationLevel)
at System.Data.Common.DbConnection.BeginTransaction(IsolationLevel isolationLevel)
at System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)
InnerException:
(Sorry it's not very readable). (The message of the internal exception mean "A new transaction is not allowed because there are other threads running in the session."
I've check, I'm not in a loop, it's purely random when it makes this exception, and I've no idea about how to avoid this.
any help will be really appreciated :)
Thank you!
EDIT: Here is an example of where I got this exception SOMETIMES
//My DataServer method, which is a singleton
[MethodImpl(MethodImplOptions.Synchronized)]
public void SaveChanges()
{
lock (_lockObject)
{
try
{
_context.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
_changeListener.ManageIDAfterInsert();
}
catch (Exception ex)
{
Logger.Instance.Error("[DataServer:SaveChanges] Got an error when trying to save an object", ex);
//HERE I've this error
}
}
}
//One example where I can have exception sometimes, this is called through a WCF service, so I have a method which attach the object and then save it
private OrderStatus AddOrderStatus(OrderStatus orderStatus)
{
DataServer.DataServer.Instance.InsertOrUpdateDetachedObject(orderStatus);
return orderStatus;
}
Without seeing your code, the short answer is that EntityFramework is not thread-safe. You're getting this error in a seemingly random pattern when two+ threads overlap when trying to try access your ObjectContext. I assume you've stuffed your context into a static variable. Either make the context a local variable or write locking around access to the ObjectContext.
If you want a more specific answer posting your code will help.
Edit
Your issue is that two threads are trying to use the context at the same time, or 1 thread is leaving a transaction open then and a second thread comes through trying to use your singleton context. Your code snippet raises more questions for me than I had before.
In your code example is _lockObject a static variable?
Why do you show the lock in SaveChanges but then explain an error is being thrown
from InsertOrUpdateDetachedObject? Can we see the code for InsertOrUpdateDetachedObject?
Does SaveChanges use the same _lockObject as all other methods that access the context directly?
Is your call to _context.SaveChanges the only way you save to the DB or do you have other areas that open transaction contexts on their own?
Your using a singleton so your context is shared across multiple calls. It might be preferable to instantiate a new new context for every WFC call.
In Microsoft IL, to call a method on a value type you need an indirect reference. Lets say we have an ILGenerator named "il" and that currently we have a Nullable on top of the stack, if we want to check whether it has a value then we could emit the following:
var local = il.DeclareLocal(typeof(Nullable<int>));
il.Emit(OpCodes.Stloc, local);
il.Emit(OpCodes.Ldloca, local);
var method = typeof(Nullable<int>).GetMethod("get_HasValue");
il.EmitCall(OpCodes.Call, method, null);
However it would be nice to skip saving it as a local variable, and simply call the method on the address of the variable already on the stack, something like:
il.Emit(/* not sure */);
var method = typeof(Nullable<int>).GetMethod("get_HasValue");
il.EmitCall(OpCodes.Call, method, null);
The ldind family of instructions looks promising (particularly ldind_ref) but I can't find sufficient documentation to know whether this would cause boxing of the value, which I suspect it might.
I've had a look at the C# compiler output, but it uses local variables to achieve this, which makes me believe the first way may be the only way. Anyone have any better ideas?
**** Edit: Additional Notes ****
Attempting to call the method directly, as in the following program with the lines commented out, doesn't work (the error will be "Operation could destabilise the runtime"). Uncomment the lines and you'll see that it does work as expected, returning "True".
var m = new DynamicMethod("M", typeof(bool), Type.EmptyTypes);
var il = m.GetILGenerator();
var ctor = typeof(Nullable<int>).GetConstructor(new[] { typeof(int) });
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Newobj, ctor);
//var local = il.DeclareLocal(typeof(Nullable<int>));
//il.Emit(OpCodes.Stloc, local);
//il.Emit(OpCodes.Ldloca, local);
var getValue = typeof(Nullable<int>).GetMethod("get_HasValue");
il.Emit(OpCodes.Call, getValue);
il.Emit(OpCodes.Ret);
Console.WriteLine(m.Invoke(null, null));
So you can't simply call the method with the value on the stack because it's a value type (though you could if it was a reference type).
What I'd like to achieve (or to know whether it is possible) is to replace the three lines that are shown commented out, but keep the program working, without using a temporary local.
I figured it out! Luckily I was reading about the unbox opcode and noticed that it pushes the address of the value. unbox.any pushes the actual value. So, in order to call a method on a value type without having to store it in a local variable and then load its address, you can simply box followed by unbox. Using your last example:
var m = new DynamicMethod("M", typeof(bool), Type.EmptyTypes);
var il = m.GetILGenerator();
var ctor = typeof(Nullable<int>).GetConstructor(new[] { typeof(int) });
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Box, typeof(Nullable<int>)); // box followed by unbox
il.Emit(OpCodes.Unbox, typeof(Nullable<int>));
var getValue = typeof(Nullable<int>).GetMethod("get_HasValue");
il.Emit(OpCodes.Call, getValue);
il.Emit(OpCodes.Ret);
Console.WriteLine(m.Invoke(null, null));
The downside to this is that boxing causes memory allocation for the boxed object, so it is a bit slower than using local variables (which would already be allocated). But, it saves you from having to determine, declare, and reference all of the local variables you need.
If the variable is already on the stack, you can go ahead and just emit the method call.
It seems that the constructor doesn't push the variable on the stack in a typed form. After digging into the IL a bit, it appears there are two ways of using the variable after constructing it.
You can load the variable that will store the reference onto the evaluation stack before calling the constructor, and then load that variable again after calling the constructor like so:
DynamicMethod method = new DynamicMethod("M", typeof(bool), Type.EmptyTypes);
ILGenerator il = method.GetILGenerator();
Type nullable = typeof(Nullable<int>);
ConstructorInfo ctor = nullable.GetConstructor(new Type[] { typeof(int) });
MethodInfo getValue = nullable.GetProperty("HasValue").GetGetMethod();
LocalBuilder value = il.DeclareLocal(nullable);
// load the variable to assign the value from the ctor to
il.Emit(OpCodes.Ldloca_S, value);
// load constructor args
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Call, ctor);
il.Emit(OpCodes.Ldloca_S, value);
il.Emit(OpCodes.Call, getValue);
il.Emit(OpCodes.Ret);
Console.WriteLine(method.Invoke(null, null));
The other option is doing it the way you have shown. The only reason for this that I can see is that the ctor methods return void, so they don't put their value on the stack like other methods. It does seem strange that you can call Setloc if the new object isn't on the stack.
After looking at the options some more and further consideration, I think you're right in assuming it can't be done. If you examine the stack behaviour of MSIL instructions, you can see that no op leaves its operand(s) on the stack. Since this would be a requirement for a 'get address of stack entry' op, I'm fairly confident one doesn't exist.
That leaves you with either dup+box or stloc+ldloca. As you've pointed out, the latter is likely more efficient.
#greg: Many instructions leave their result on the stack, but no instructions leave any of their operands on the stack, which would be required for a 'get stack element address' instruction.
Just wrote a class that does what the OP is asking... here's the IL code that C# compiler produces:
IL_0008: ldarg.0
IL_0009: ldarg.1
IL_000a: newobj instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
IL_000f: stfld valuetype [mscorlib]System.Nullable`1<int32> ConsoleApplication3.Temptress::_X
IL_0014: nop
IL_0015: ret