Contents tagged with .NET

  • NHibernate Pitfalls: Specifying Property Types

    This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

    When you want to specify an NHibernate type (implementation of NHibernate.Type.IType) for a property using mapping by code, you might be tempted to do something like this:

       1: ca.Property(x => x.SomeProperty, x =>
       2: {
       3:     x.Type<StringClobType>();
       4: });

    If you try this, you will get a nasty exception about the type not having a public parameterless constructor. Ouch!

    The thing is: NHibernate types are supposed to be stateless, and therefore it does not make sense to have several instances of a type, that is why NHibernate encourages us to use the static fields defined in the NHibernateUtil class and that is also why most of the built-in types don’t have a public parameterless constructor.

    So, if you want to implement your own types, you can certainly add a public parameterless constructor to them and use the above syntax, but if you are going to use the built-in types, you should instead use:

       1: ca.Property(x => x.SomeProperty, x =>
       2: {
       3:     x.Type(NHibernateUtil.StringClob);
       4: });

    Read more...

  • Simple Calculations With .NET

    The idea for this post came from a recent post of Salvador Gascon (@salvadorgascon): http://salvadorgascon.wordpress.com/2014/09/27/how-evaluate-math-expressions/.

    For simple math expressions calculation I use the DataTable class. Very simple and we already have it! Also, we can use some SQL expressions (list at http://msdn.microsoft.com/en-us/library/system.data.datacolumn.expression.aspx):

       1: var table = new DataTable();
       2: table.Columns.Add("A", typeof(int));
       3: table.Columns.Add("B", typeof(int));
       4:  
       5: var c = new DataColumn("C"){ Expression = "[A] + [B]" };
       6: table.Columns.Add(c);
       7:  
       8: var d = new DataColumn("D"){ Expression = "ISNULL([A], [B])" };
       9: table.Columns.Add(d);
      10:  
      11: table.Rows.Add(1, 2);
      12:  
      13: var resultc = table.Rows[0]["C"];    //3
      14: var resultd = table.Rows[0]["D"];    //1

    It can also be used for aggregations:

       1: var sum = table.Compute("SUM([A])", String.Empty);
       2: var avg = table.Compute("AVG([B])", String.Empty);

    For the list of supported expressions, see http://msdn.microsoft.com/en-us/library/system.data.datatable.compute.aspx.

    Easy, and no need for external libraries! Winking smile

    Read more...

  • Cascading Drop Down Lists in SharePoint

    Introduction

    A common request is the ability to have one drop down list (the child) being filled after another one (the parent) has; this is usually called cascading drop down lists.

    There are several solutions for this, most of what I’ve found use JavaScript. It isn’t required, and a very simple solution exists, both for SharePoint 2010 as well as 2013.

    Set Up

    First, let’s create two lists: Parent and Child. Connect the Child to the Parent through a lookup field that points to the Parent’s ID field and call this lookup Parent. Add some records to it.

    SharePoint Designer

    On SharePoint Designer create a new web part page. Find some space and add two DropDownList controls:

       1: <asp:DropDownList runat="server" ID="parentList" DataSourceID="parentDataSource" DataTextField="Title" DataValueField="ID" AutoPostBack="true" Width="200px" />
       2:  
       3: <br/>
       4:  
       5: <asp:DropDownList runat="server" ID="childList" DataSourceID="childDataSource" DataTextField="Title" DataValueField="ID" Width="200px" EnableViewState="false"/>

    Next, add two SPDataSource controls:

       1: <SharePoint:SPDataSource runat="server" DataSourceMode="List" SelectCommand="&lt;View&gt;&lt;/View&gt;" ID="parentDataSource">
       2:     <SelectParameters>
       3:         <asp:Parameter Name="ListID" DefaultValue="{828362D7-E519-4522-86AF-DF90AC023719}"/>
       4:     </SelectParameters>
       5: </SharePoint:SPDataSource>
       6:  
       7: <SharePoint:SPDataSource runat="server" DataSourceMode="List" SelectCommand="&lt;View&gt;&lt;Query&gt;&lt;Where&gt;&lt;Eq&gt;&lt;FieldRef Name=&quot;Parent&quot;/&gt;&lt;Value Type=&quot;Lookup&quot;&gt;{parent}&lt;/Value&gt;&lt;/Eq&gt;&lt;/Where&gt;&lt;/Query&gt;&lt;/View&gt;" ID="childDataSource">
       8:     <SelectParameters>
       9:         <asp:Parameter Name="ListID" DefaultValue="{F83375F4-D4EB-48AF-8CD9-5E773BC7692F}"/>
      10:         <asp:ControlParameter ControlID="parentList" PropertyName="SelectedValue" Name="parent" />
      11:     </SelectParameters>
      12: </SharePoint:SPDataSource>

    Pay attention to a couple of things:

    • We are retrieving lists from the same site, but it is possible to get them from different sites as well, just change the DataSourceMode property and the SelectCommand accordingly;
    • You need to replace the ListID values in each Parameter for the proper ones: the GUID of the Parent list and the GUID of the Child list;
    • I am using the standard ID and Title columns, but you can use whatever you want;
    • If you give other name to the lookup field other than Parent, you need to change the SelectCommand property accordingly (FieldRef element);
    • You can give any name you like to the DropDownList controls, but if you change the name of the parent one, don’t forget to update the ControlID property of the ControlParameter in the child’s SPDataSource;
    • For editing the child SPDataSource’s SelectCommand property, you should use the Tag Properties window, because the XML there is not encoded;
    • Disable View State for the child DropDownList by setting EnableViewState to false;
    • Leave AutoPostBack set to true for the parent DropDownList, this causes the page to reload when the parent changes.

    Improvements

    If you prefer to have the parent DropDownList initially unselected, use the following markup instead:

       1: <asp:DropDownList runat="server" ID="parentList" DataSourceID="parentDataSource" DataTextField="Title" DataValueField="ID" AutoPostBack="true" Width="200px" AppendDataBoundItems="true">
       2:     <asp:ListItem Selected="true" Text="" Value="-1"/>
       3: </asp:DropDownList>

    AppendDataBoundItems makes sure that any items added from a data source control are appended to any existing ones.

    Another useful improvement would be to wrap all controls inside an UpdatePanel. This way, when the parent DropDownList changes, it won’t cause a full page postback.

    Of course, you can have any number of nested DropDownList controls, just follow the same logic.

    Read more...

  • NHibernate Pitfalls: One Shot Delete and Inverse Collections

    This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

    When you clear all items in an entity’s collection by calling it’s Clear() method, if it has cascading option all-delete-orphan, NHibernate will then delete (when flushing) all of the collection’s items. That is because it considers them to be children of the entity and we explicitly told NHibernate that the entity no longer has any (very sad, I know! Winking smile).

    Ideally, we would expect NHibernate to only issue a single DELETE, as this:

       1: DELETE FROM children
       2: WHERE parent_id = @p0
       3: /*
       4: AND some_filter_value = @p1
       5: */

    That, however, is not the case for inverse collections, which are the most common ones. In this case, NHibernate issues N DELETEs, one for each entity, which is bad in terms of performance:

       1: DELETE FROM children
       2: WHERE children_id = @p0;
       3:  
       4: DELETE FROM children
       5: WHERE children_id = @p1;
       6:  
       7: -- and so on

    The NHibernate reference has an incorrection, in which it states exactly the opposite:

    “one-shot-delete apply to collections mapped inverse="true"”

    There is an open issue at NHibernate JIRA meant to fix this, https://nhibernate.jira.com/browse/NH-3708, but it is not so simple, so we’ll have to wait! Sad smile

    In the meantime, even though it’s not so intuitive, you can use one of the delete methods I describe in this post.

    Read more...

  • NHibernate Pitfalls: Deletes

    This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

    While I was writing Deleting Entities in NHibernate, I noticed that actually it referred some pitfalls concerning deleting, so I decided to add them to the proper collection.

    There are several ways to delete entities in NHibernate, as you can see in the referenced post. The problems with each approach are:

    • Using Executable HQL: no cascade to related associations occurs, no events are raised;
    • Using Delete with an entity proxy: forces loading of all cascaded lazy associations before deleting; requires a Flush to apply changes (if it needs to be explicit or not depends on you flush settings);
    • Using Delete with a query string: all items are loaded into the session (not a single DELETE statement), no cascade occurs, no events are raised, no notification about the number of affected records and also requires a flush.

    Read more...

  • NHibernate Pitfalls: Get and Filters

    This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

    This was suggested a long time ago by Kelly Brownsberger (@kbrowns). What happens is, even if you have filters defined, they are not applied on a call to ISession.Get<T>(). This is by design: you are explicitly asking for an entity with some id, so NHibernate just returns you that. On the other hand, static where restrictions defined at the entity level still apply.

    Read more...

  • NHibernate Pitfalls: Criteria and Collections of Non-Entities

    This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

    Criteria API – and QueryOver, for that matter, which is just a strongly-typed wrapper around Criteria – cannot work with collections of non-entities: elements, components or dictionaries. If you need to work with those, you need to use one of the other APIs – LINQ, HQL or SQL.

    Read more...

  • Deleting Entities in NHibernate

    This post was motivated by a conversation with Salvador Gascon (@salvadorgascon). Might even go to the pitfalls section… Anyway, the problem is: how many ways there are to delete an entity in NHibernate? And what are the advantages/disadvantages of each?

    First, we have the classic one, using ISession.Delete(), which all NHibernate developers should be familiar with:

       1: var product = session.Get<Product>(id);
       2:  
       3: session.Delete(product);
       4:  
       5: session.Flush();

    Using ISession.Get<T>(), you force an entity – and all of its non-lazy associations and properties – to be loaded from the database. When you delete it, all associations marked for cascade delete will also be deleted.

    If you don’t want to load the entity from the database in order to delete it, you can use ISession.Load<T>(), for entities marked as lazy, this will return a proxy instead:

       1: var product = session.Load<Product>(id);
       2:  
       3: session.Delete(product);
       4:  
       5: session.Flush();

    Do note, however, that when Delete is called, the entity will still be loaded, as well as all its non-lazy associations. Flushing is required.

    For better performance, we can use Executable HQL:

       1: session.CreateQuery("delete from Product p where p.ProductId = :id")
       2: .SetParameter("id", id)
       3: .ExecuteUpdate();

    This will translate to a single plain old SQL DELETE command, so no entity will be loaded into the session. This has a big disadvantage, though: no cascade deletes will occur. This means that you may get exceptions due to foreign key violations. A good thing is that it returns the number of deleted records.

    Another way to delete is through an overload of the Delete method:

       1: session.Delete(String.Format("from Product p where p.ProductId = {0}", id));
       2:  
       3: session.Flush();

    In this case, we are providing the id in the query string, which is not good, mainly for performance reasons – with NHibernate HQL, SQL injections are much more difficult to do. A better alternative is to use positional parameters:

       1: session.Delete("from Product p where p.ProductId = ?", id, NHibernateUtil.Int32);

    In this case, together with the id, we also need to supply its type. Does not cascade nor return the number of deleted records.

    Read more...

  • NHibernate Pitfalls: HQL Delete Does Not Cascade

    This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.

    When you issue an HQL delete statement over an entity, you may be surprised to find out that it will not cascade to any configured associations it may have:

       1: session.CreateQuery("delete from Order o where o.Id = :id").SetParameter("id", 10).ExecuteUpdate();

    If you really want to cascade associations, you will have to load the entity explicitly and then call ISession.Delete() upon it.

    Read more...