VB6 and VB.Net developers know this feature: "Late Binding" and C# developers have often ridiculed that option. Buit it seems that the next version of Visual Studio will support a feature called "Dynamic type support". An article on this new feature can be found here, at Charlie Calvert's Community Blog. James Manning likes the idea but has some remarks about the suggested implementation. You can read about that here.
Currently, C# developers will need to use reflection to instantiate the object and discover methods and properties. The way the C# team are thinking about the implementation will make dynamic objects work something like this:
static void Main(string args)
object myDynamicObject = GetDynamicObject();
myDynamicObject.SomeMethod(); // call a method
myDynamicObject.someString = "value"; // Set a field
myDynamicObject = 25; // Access an indexer
If you've worked with reflection before, you immediately see how simple this will be. And the way it will be integrated into the CLR will allow other languages to use this as well.
Looks like another promising feature for C#!
Just found this on Dan''s Blog, the SQL Server 2008 CTP is available for download. If you're interested in the latest version of SQL Server, then follow any of the links below.
The download can be found here
If you want to know what's new in this CTP, look here
Samples of SQL code can be found on CodePlex
I was pointed to the Sysinternals section on TechNet recently. I've seen some of the tools provided there before, but I always seem to forget where I could find them. So now, as a permanent reminder, a short blog post. From the Sysinternals website:
The Sysinternals web site was created in 1996 by Mark Russinovich and Bryce Cogswell to host their advanced system utilities and technical information. Microsoft acquired Sysinternals in July, 2006. Whether you’re an IT Pro or a developer, you’ll find Sysinternals utilities to help you manage, troubleshoot and diagnose your Windows systems and applications. If you have a question about a tool or how to use them, please visit the Sysinternals Forum for answers and help from other users and our moderators.
In my current project, we calculate the status of tasks that a user needs to do and store the status in a table. This happens on a daily basis. Once every week, we calculate which items are overdue and inform the user by email to take appropriate action. However, sometimes our users complain that they receive such an email and that there aren't any tasks that require immediate action.
We know that this happens, but since we calculate the status once per day and when the user logs on to the application, we cannot really see why this happens. What we needed was a way to see when a tasks moves to another state. We decided to create a history table which contains the information in our status table and update that history table using a trigger. But the examples we found in Books on Line and other resources on the web just didn't give us the information we needed.
So I called my good friend Patrick Wellink who I know to be a SQL guru. He had written a generic trigger which can be used to audit changes and posted this on SqlServerCentral.Com. The script looks like this:
CREATE TRIGGER TRG_##YOUR_TABLE##
-- JUST CHANGE ##YOUR_TABLE## INTO YOUR OWN TABLENAME TO MAKE IT WORK
DECLARE @ACT CHAR(6)
DECLARE @DEL BIT
DECLARE @INS BIT
DECLARE @SQLSTRING VARCHAR(2000)
SET @DEL = 0
SET @INS = 0
IF EXISTS (SELECT TOP 1 1 FROM DELETED) SET @DEL=1
IF EXISTS (SELECT TOP 1 1 FROM INSERTED) SET @INS = 1
IF @INS = 1 AND @DEL = 1 SET @ACT = 'UPDATE'
IF @INS = 1 AND @DEL = 0 SET @ACT = 'INSERT'
IF @DEL = 1 AND @INS = 0 SET @ACT = 'DELETE'
IF @INS = 0 AND @DEL = 0 RETURN
IF NOT EXISTS (SELECT * FROM SYSOBJECTS WHERE ID = OBJECT_ID(N'[DBO].[AUDIT_##YOUR_TABLE##]') AND OBJECTPROPERTY(ID, N'ISUSERTABLE') = 1)
-- CREATE A MEMORY TABLE CONTAINING THE FIELDS AND TYPES OF THE TABLE
DECLARE @MEMTABLE TABLE
ID INT IDENTITY
-- INSERT THE COLUMNAMES AND THE DATATYPES
WHERE ID = OBJECT_ID('[DBO].[##YOUR_TABLE##]')
ORDER BY COLID
DECLARE @CUR INTEGER
DECLARE @MAX INTEGER
DECLARE @SQLSTR AS VARCHAR(8000)
DECLARE @CURCOL SYSNAME
DECLARE @COLTYPE AS VARCHAR(10)
-- SETUP VARIABLES
SET @SQLSTR = ''
SELECT @MAX = MAX(ID) FROM @MEMTABLE
-- LOOP EVEY FIELD
WHILE @CUR <= @MAX
-- GET VALUES FROM THE MEMTABLE
SELECT @CURCOL = COLUMNAME,@COLTYPE = TYPENAME FROM @MEMTABLE WHERE ID = @CUR
IF @COLTYPE = 'INT' OR @COLTYPE = 'BIGINT' OR @COLTYPE='UNIQUEIDENTIFIER'
-- WE DO WANT TO COPY INT/BIGINT/UNIQUEIDENTIFIER FIELDS BUT IF THEY ARE AN
-- IDENTITY OR A ROWGUIDCOLUMN WE DO NOT WANT TO COPY THAT ATTRIBUTES
SET @SQLSTR = @SQLSTR + ' CAST('+@CURCOL + ' AS '+@COLTYPE+') AS [' + @CURCOL +'] '
-- ANOTHER FIELD DO NOTHING JUST COPY IT AS IT IS
SET @SQLSTR = @SQLSTR + ' '+@CURCOL + ' AS [' + @CURCOL +'] '
IF @CUR <= @MAX - 1 SET @SQLSTR=@SQLSTR + ','
SET @CUR = @CUR + 1
-- ADD THE AUDIT FIELDS
SET @SQLSTR = @SQLSTR +',CAST('' '' AS CHAR(6)) AS TRG_ACTION,CAST(GETDATE() AS DATETIME) AS TRG_DATE'
-- SET UP THE SELECT FOR CREATING THE AUDIT TABLE
SET @SQLSTR = 'SELECT TOP 0 ' + @SQLSTR + ' INTO [DBO].[AUDIT_##YOUR_TABLE##] FROM [DBO].[##YOUR_TABLE##]'
IF @ACT = 'INSERT' INSERT [DBO].[AUDIT_##YOUR_TABLE##] SELECT *,'INSERT' ,GETDATE() FROM INSERTED
IF @ACT = 'DELETE' INSERT [DBO].[AUDIT_##YOUR_TABLE##] SELECT *,'DELETE' ,GETDATE() FROM DELETED
IF @ACT = 'UPDATE' INSERT [DBO].[AUDIT_##YOUR_TABLE##] SELECT *,'UPDATE' ,GETDATE() FROM INSERTED
It does almost everything we needed. It copies the information to a new table when something happens to the row in the original table. Thanks Patrick for helping us with this script.
We modified the code for the update section, because we only wanted to store the old information in the AUDIT table when certain fields are modified:
INNER JOIN DELETED ON DELETED.StatusID = INSERTED.StatusID
WHERE (INSERTED.Status <> DELETED.STATUS)
OR (INSERTED.CountAlerts <> DELETED.CountAlerts)
OR (INSERTED.AlertViewed <> DELETED.AlertViewed)
This way, we get the information as it was before the update and only when the fields that we want to monitor are changed. Works great!
No matter what people say, managed code applications can (and will) leak memory. I bumped into a blog post on MSDN today which describes how memory leaks in WPF applications can be avoided and found should they occur. From the blog post:
In this blog I wanted to:
- Show coding practices that can cause memory leaks which are more unique to WPF-base apps
- Show how to avoid these leaks
- Discuss the tools and techniques available to detect the leaks
The article contains links to tools that can help you track memory leaks. It also contains links to other resources about this subject. Be sure to check it out if you experience memory problems in your managed code.
You can find the article with all the information here: http://blogs.msdn.com/jgoldb/archive/2008/02/04/finding-memory-leaks-in-wpf-based-applications.aspx
Everyone is entitled to his/her opinion. The author of this article
certainly has an opinion about a number of Microsoft products. There are even some products I had never heard of before. The list contains the following Microsoft products:
- Microsoft Home Routers
- Microsoft Mira
- Microsoft Origami
- Microsoft SPOT watch
- Microsoft BOB
- Microsoft Vista Ultimate
- The MSN Music Store and "Plays for Sure" audio format.
- The Microsoft Surface PC
Like I said, it's the authors opinion, not mine. I was surprised that Windows ME wasn't in the list, as were other people around me. I guess we all have a Microsoft product we'd like to see on this list.