Monday, September 29, 2008
Do-not-break-the-testcases 101
Friday, September 5, 2008
Chrome
Wednesday, May 7, 2008
Nullable enums
public enum Foo { X, Y };
[...]
public Foo Bar { set { ... } }
[...]
PropertyInfo prop = obj.GetType().GetProperty("Bar");
prop.SetValue(obj, (object)1, null);
I.e. you can use reflection to set the value of a property of an enum type using its integer value. (You could also just cast it like so: obj.Bar = (Foo)1;, but that's not quite as interesting, for reasons that will be revealed later.)
Also, a boxed value and a boxed nullable value have the same representation, right? They are both pointers to a small object containing the primitive. As the following code shows, boxed integers and boxed nullable integers are interchangeable:
int intValue = 1;
int? nullableIntValue = 1;
object boxedInt = intValue;
object boxedNullableInt = nullableIntValue;
intValue = (int)boxedNullableInt;
nullableIntValue = (int?)boxedInt;
And, not surprisingly, the same holds for enum values, now demonstrated using reflection as in our first example:
public Foo? Bar { set { ... } }
[...]
prop.SetValue(obj, (object)Foo.X, null);
Now, combining these two examples, what do you think the following code would do?
public Foo? Bar { set { ... } }
[...]
prop.SetValue(obj, (object)1, null);
If you, like me, thought it would happily set the property to the enum value correspoding to 1, in this case Foo.X, you'd be wrong. Instead it throws the following exception:
Object of type 'System.Int32' cannot be converted to type 'System.Nullable`1
Huh? The .net designers may know why this is, and they may even have a good reason for it, but to me it just seems plain weird. It is worth noting that obj.Bar = (Foo?)1; works just fine.
This issue came up when mapping objects from database tables, using integers to represent enum values. I've reluctantly added the following workaround to my mapping code:
PropertyInfo prop = [...]
object val = [...]
if ((prop.PropertyType.IsGenericType) &&
(prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
Type targetType = prop.PropertyType.GetGenericArguments()[0];
if (targetType.IsEnum)
val = Enum.ToObject(targetType, val);
}
prop.SetValue(obj, val, null);
Sunday, April 20, 2008
Bad service
The problem is that Service Broker needs to end all open conversations, and it does so in one transaction. If you have many open conversations troubles arise.
I found the following link which describes a fix for the problem. I'm reprinting the fix here in case the link goes bad:
declare crsConversations cursor for
select conversation_handle
from sys.conversation_endpoints e
join sys.services s on s.service_id = e.service_id
where s.name = 'myservicename';
open crsConversations;
declare @dh uniqueidentifier;
declare @batch int;
select @batch = 0;
begin transaction
fetch next from crsConversations into @dh;
while @@fetch_status =0
begin
-- replace this with end conversation @dh with error ... if
-- and error has to be sent to the peer
--
end conversation @dh with cleanup;
-- commit every 1000 conversations ended
select @batch = @batch + 1;
if @batch > 999
begin
commit transaction;
begin transaction;
end
fetch next from crsConversations into @dh;
end
commit transaction;
close crsConversations;
deallocate crsConversations;
go
drop service 'myservicename'
go
Now, if you have this problem the real question is, why are you leaking open conversations?
Saturday, April 19, 2008
(contd.)
http://blogs.codegear.com/andersivner.
I've since then left Borland/CodeGear and now work for Sigma.
The product I worked on at Borland/CodeGear, ECO, is now available from CapableObjects, a company run by my friends and former collegues. They have recently released ECO for Visual Studio. Way cool!