nHibernate and Remoting/Shallow Serialization
by Alec Horn on Oct.28, 2009, under .NET/C#, Coding, nHibernate
So, recently had an issue with Weborb and nHibernate serializing our entire object model due to deep serialization. After much research and my lack of deep knowledge of nHibernate I came across http://trentacular.com/tag/nhibernate/. Shamelessly stolen, of course this solved my problems immediately allowing me to specify n levels of serialization to be kept down the line. I made a few alterations to allow for collections to be serialized:
if (nhType.IsCollectionType)
{
object propertyValue = propertyInfo.GetValue(unproxiedObject, null);
if (propertyValue == null)
continue;
if (propertyValue is PersistentBag)
{
PersistentBag holder = (PersistentBag)propertyValue;
for (int j = 0; j < holder.Count; j++)
{
holder[j] = holder[j].UnproxyObjectTree(sessionFactory, maxDepth - 1);
}
propertyInfo.SetValue(
unproxiedObject,
holder,
null);
}
else if (propertyValue is ISet)
{
ISet holder = (ISet)propertyValue;
ArrayList tempcoll = new ArrayList();
foreach (object o in (IEnumerable)propertyValue)
{
tempcoll.Add(o);
}
for (int j = 0; j < tempcoll.Count; j++)
{
tempcoll[j] = tempcoll[j].UnproxyObjectTree(sessionFactory, maxDepth - 1);
}
holder.Clear();
holder.AddAll(tempcoll);
propertyInfo.SetValue(
unproxiedObject,
holder,
null);
}
continue;
}
Anonymous methods and Delegates
by Alec Horn on Sep.21, 2009, under .NET/C#, Coding
So, I’m currently working on a Windows forms application built by a coworker and adding some threading to it to provide a more enhanced interface.
Of course we come into the issue of thread locking, and of course Invoke must be used. We’re in .NET 3.5, might as well get some of the benefits of the latest framework, right? Well, turned out to be a bit more confusing than I first thought.
Ex:
delegate bool GetBoolDelegate();
int GetBoolValue()
{
if (!InvokeRequired)
return (bool)vart.SelectedIndex;
else
return (bool)Invoke(new GetBoolDelegate(GetBoolValue), null);
}
The pre 2.0 way of doing things, move along and try:
bool regchecked = (bool)this.Invoke(
delegate()
{
return chkRegression.Checked;
}
);
Which gives the following error:
Cannot convert anonymous method to type ‘System.Delegate’ because it is not a delegate type
There are several ways around this, the easiest is:
public delegate bool MethodBoolInvoke();
bool regchecked = (bool)this.Invoke(
(MethodBoolInvoke)delegate()
{
return chkRegression.Checked;
}
);
And, the final simple example of invoking for general items:
this.Invoke( (MethodInvoker)delegate() {this.Cursor = Cursors.WaitCursor; });
Changing the Visual Studio ‘Developer Type’
by Alec Horn on Jun.19, 2009, under Visual Studio .NET
So, every once and a while I accidently hit the wrong setup type when opening a brand new copy of VS after my 483rd format, and F5 is no longer debug, F6 no longer rebuild, and I realize that I *should* have hit “Visual C# Developer”.
Alas, MSDN has a solution:
http://msdn.microsoft.com/en-us/library/f1z20s6z.aspx
Just keep in mind it will overwrite some other format settings if you have them set.
How not to lock your database server for large deletes.
by Alec Horn on May.14, 2009, under Uncategorized
So one of my coworkers recently brought down a website accidently since someone broke the session cleaning job. So, he of course runs the procedure to delete all of the old data, and kaboom it places a lock on the table while it deletes a few hundred thousand rows.
Cute except that without that table being able to be accessed no requests would technically go through. The workaround? Simply do small units of work at a time:
WHILE 1=1 BEGIN DELETE TOP (1000) FROM [db].[dbo].[table] WHERE Expires < @now; IF @@rowcount = 0 BREAK; END
How to convert an office 2007 document to 2003.
by Alec Horn on Mar.30, 2009, under .NET/C#, Coding
So, backwards converting seemed to be impossible, and is give or take but if you can interact with the desktop here’s a way to do it that’s beyond ugly, cludgy, and I wish someone had a better solution… Oh, this is to interact with OFFICE12\Moc.exe, best of luck!
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Threading; using System.IO; namespace t { class Program { static void Main(string[] args) { Program.ProcessChecker.Proc(); Console.ReadLine(); } static class ProcessChecker { internal static class NativeMethods { [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] public static extern bool EnumWindows(EnumWindowsProcDel lpEnumFunc, Int32 lParam); [DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, ref Int32 lpdwProcessId); [DllImport("user32.dll")] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, Int32 nMaxCount); [DllImport("user32.dll")] public static extern bool SetWindowText(IntPtr hWnd, string lpString); [DllImport("user32.dll")] public static extern int GetFocus(); [DllImport("user32.dll")] public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach); [DllImport("kernel32.dll")] public static extern uint GetCurrentThreadId(); [DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(int hWnd, int ProcessId); [DllImport("user32.dll")] public static extern int GetForegroundWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern int SendMessage(int hWnd, int Msg, int wParam, StringBuilder lParam); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); public enum GetWindow_Cmd : uint { GW_HWNDFIRST = 0, GW_HWNDLAST = 1, GW_HWNDNEXT = 2, GW_HWNDPREV = 3, GW_OWNER = 4, GW_CHILD = 5, GW_ENABLEDPOPUP = 6 } public const int SW_SHOWNORMAL = 1; } const int WM_SETTEXT = 12; const int WM_GETTEXT = 13; public delegate bool EnumWindowsProcDel(IntPtr hWnd, Int32 lParam); static private bool EnumWindowsProc(IntPtr hWnd, Int32 lParam) { int processId = 0; uint remoteThreadId = NativeMethods.GetWindowThreadProcessId(hWnd, ref processId); StringBuilder WindowText = new StringBuilder(5000); NativeMethods.GetWindowText(hWnd, WindowText, 5000); StringBuilder v_szbTest2 = new StringBuilder(99); NativeMethods.GetClassName(hWnd, v_szbTest2, 99); if (WindowText.ToString().Equals("Save As") && processId.Equals(lParam)) { uint currentThreadId = NativeMethods.GetCurrentThreadId(); NativeMethods.AttachThreadInput(remoteThreadId, currentThreadId, true); IntPtr i = IntPtr.Zero; i = NativeMethods.GetWindow(hWnd, (uint)NativeMethods.GetWindow_Cmd.GW_CHILD); for (; i.ToInt32() > 0; ) { i = NativeMethods.GetWindow(i, (uint)NativeMethods.GetWindow_Cmd.GW_HWNDNEXT); StringBuilder v_szbTest3 = new StringBuilder(99); NativeMethods.GetClassName(i, v_szbTest3, 99); StringBuilder builder = new StringBuilder(500); builder.Append("c:\\Hey look a text.xls"); if (v_szbTest3.ToString().Equals("ComboBoxEx32")) { NativeMethods.SendMessage(i.ToInt32(), WM_SETTEXT, builder.Capacity, builder); } StringBuilder v_szbText = new StringBuilder(256); NativeMethods.GetWindowText(i, v_szbText, 256); if (v_szbTest3.ToString().Equals("Button") && v_szbText.ToString().Equals("&Save")) { //Save! var BM_CLICK = 0xf5; NativeMethods.SendMessage(i.ToInt32(), BM_CLICK, 0, builder); NativeMethods.AttachThreadInput(remoteThreadId, currentThreadId, false); //Lets wait till we can access the file. while (true) { try { FileStream fso = File.Open(builder.ToString() + ".xls", FileMode.Open, FileAccess.Write); fso.Close(); //kill our proc Process moc = Process.GetProcessById(lParam); moc.Kill(); return true; } catch (IOException x) { Console.WriteLine(x); Thread.Sleep(10); } } } } } return true; } static public bool Proc() { Process[] v_oProcs = Process.GetProcesses(); foreach (Process proc in v_oProcs) { if (proc.ProcessName.Equals("Moc")) { NativeMethods.EnumWindows(new EnumWindowsProcDel(EnumWindowsProc), proc.Id); return false; } } return true; } } #region EnumWindows /// /// EnumWindows wrapper for .NET /// public class EnumWindows { #region Delegates private delegate int EnumWindowsProc(IntPtr hwnd, int lParam); #endregion #region UnManagedMethods private class UnManagedMethods { [DllImport("user32")] public extern static int EnumWindows( EnumWindowsProc lpEnumFunc, int lParam); [DllImport("user32")] public extern static int EnumChildWindows( IntPtr hWndParent, EnumWindowsProc lpEnumFunc, int lParam); } #endregion #region Member Variables private List<IntPtr> items = null; #endregion /// /// Returns the collection of windows returned by /// GetWindows /// public List<IntPtr> Items { get { return this.items; } } /// /// Gets all top level windows on the system. /// public void GetWindows() { this.items = new List<IntPtr>(); UnManagedMethods.EnumWindows( new EnumWindowsProc(this.WindowEnum), 0); } /// /// Gets all child windows of the specified window /// /// Window Handle to get children for public void GetWindows( IntPtr hWndParent) { this.items = new List<IntPtr>(); UnManagedMethods.EnumChildWindows( hWndParent, new EnumWindowsProc(this.WindowEnum), 0); } #region EnumWindows callback /// /// The enum Windows callback. /// /// Window Handle /// Application defined value /// 1 to continue enumeration, 0 to stop private int WindowEnum( IntPtr hWnd, int lParam) { if (this.OnWindowEnum(hWnd)) { return 1; } else { return 0; } } #endregion /// /// Called whenever a new window is about to be added /// by the Window enumeration called from GetWindows. /// If overriding this function, return true to continue /// enumeration or false to stop. If you do not call /// the base implementation the Items collection will /// be empty. /// /// Window handle to add /// True to continue enumeration, False to stop protected virtual bool OnWindowEnum( IntPtr hWnd) { items.Add(hWnd); return true; } #region Constructor, Dispose public EnumWindows() { // nothing to do } #endregion } #endregion EnumWindows } }
Entity SQL, Joins and the EntityDataSource with Child Relations
by Alec Horn on Dec.19, 2008, under .NET/C#, ADO.NET, Coding
So, yesterday I actually started working with the Entity framework with a tad more complex queries than the basic select of a single Entity. The first issue I ran into is the flattening of a single Entity 1* Entity relationship. By default the Entity framework and the EntityDataSource actually keeps something similar to an DataTable->ChildDataTable relationship with a prebuilt relationship. Unfortunately the ability to flatten this data is not inherently built in, and join syntax needs to be used:
SELECT E.ID, E.Field, r.Field2 from EntitySet AS E INNER JOIN Entity2Set AS r ON r.Entity = E
Which creates our flattened list of Entities for us based on the defined relationship.
Secondly: EntityDataSource and 1-1 relationships/child objects/picklists. This is much easier to do via the Entity framework and is simply defined via the “Include” parameter.
Ex:
<asp:EntityDataSource ID="x_EntityDataSource" runat="server" ConnectionString="name=DataEntities" DefaultContainerName="DataEntities" Where="it.ID = @EntityID" EntitySetName="EntitySet" EnableUpdate="True" Include="SubEntity"> <WhereParameters> <asp:QueryStringParameter Name="EntityId" QueryStringField="ID" Type="Int32" /> </WhereParameters> </asp:EntityDataSource>
Which provides us with the Entity, and a secondary child Entity which is an FK relationship to a single value.
And, lastly some great posts from the Microsoft team:
http://blogs.msdn.com/diego/archive/2008/05/13/entitydatasource-to-wrap-or-not-to-wrap.aspx
http://blogs.msdn.com/diego/archive/2008/05/24/entitydatasource-s-flattening-of-complex-type-properties.aspx
http://blogs.msdn.com/zlatkom/archive/2007/07/10/entity-sql.aspx
Iterating through an embedded resources file.
by Alec Horn on Dec.16, 2008, under .NET/C#, Coding
So, I decided to try a new format for handling picklists (database mappings) and decided to leave a full code based Enum model with resources files to map to proper names. From there the SQL can be generated during our build process to populate the database. Now, the issue came in when you need to go from a sane (display) value back to the ID or Enum value. In order to get a ResourceReader on an embedded resource, the following works…
ResourceReader v_oReader = new ResourceReader(typeof(T).Assembly.GetManifestResourceStream(typeof(T).FullName + "DataSource.resources")); try { foreach (DictionaryEntry entry in v_oReader) { if (entry.Value.ToString().Equals(p_szDisplayValue)) { return (T)(Enum.Parse(typeof(T), entry.Key.ToString())); } } throw new ApplicationException(String.Format("Unable to match value for '{0}'.", p_szDisplayValue )); } finally { v_oReader.Close(); v_oReader = null; }
Where T is the Enum, and this code assumes that the embedded resx file is stored at Namespace.EnumDataSource.resources