News, examples, tips, ideas and plans.
Thoughts around ORM, .NET and SQL databases.

Saturday, January 29, 2011

DataObjects.Net v.4.4 Beta 2 and v.4.3.7

Development branch

DataObjects.Net 4.4 branch is updated to 4.4 Beta 2 version. This release is mainly dedicated to totally reworked Prefetch module. Changes applied to DataObjects.Net 4.3 branch have been already ported to this version. For further information and usage examples see DataObjects.Net 4.4 Beta 2 Release Notes.

Due to major changes in API, usage of this release in projects, based on the previous version of DataObjects.Net, might require some fixing of assembly references or namespaces. Migration path is described in the Release Notes file.

Download DataObjects.Net 4.4 Beta 2

Stable branch

DataObjects.Net 4.3 branch is updated to 4.3.7 version. This release includes the following changes:

Features:
Updates:
  • Npgsqlprovider is updated to the latest version (2.0.11.0)
  • More informative descriptions are added to Storage.Model collections
Fixes:
Misc
DataObjects.Net has been finally reached Microsoft Visual Studio gallery. If you feel that it is worth any positive feedback, please drop a line in Reviews section. Help us making DataObjects.Net popular.

Download DataObjects.Net 4.3.7

Friday, January 14, 2011

How to handle non-persistent collection

Today we've faced with an interesting scenario from Jensen: an Entity has a non-persistent collection which should be serialized to and deserialized from a persistent field on demand. Here is how the problem was initially described on the support website (go to the end of the page):

Object A should contain a list of samples (object T). I could do something like
A a = GetA();
a.Load(); (convert the byte[] to a List)
and something like
a.Store(); (convert the List to a byte[])
m_transactionScope.Commit();
But I don't like calling a Load() and Store() function each time, it would be easier if this could be automated. When A is loaded from the database it should Load(), when saved to the database it should Store().

After several experiments I've found a solution.

1. Add a set of properties to the desired class.
public class MyEntity : Entity {
    ...
    [Field] // Is used as an indicator that collection has been changed
    private bool IsChanged { get; set; }

    [Field] // Backing field for serialized collection value
    private byte[] CollectionValue { get; set; }

    // The collection itself. Note that it is not persistent.
    public ObservableCollection<int> Collection { get; set; }
    ...

2. Add proper methods for serialization & deserialization:
    private static byte[] Serialize(ObservableCollection<int> collection)
    {
      var ms = new MemoryStream();
      var bf = new BinaryFormatter();
      bf.Serialize(ms, collection);
      return ms.ToArray();
    }

    private static ObservableCollection<int> Deserialize(byte[] bytes)
    {
      var bf = new BinaryFormatter();
      var ms = new MemoryStream(bytes);
      return (ObservableCollection<int>) bf.Deserialize(ms);
    }

3. Add Entity initializer & event handlers:
    protected override void OnInitialize()
    {
      base.OnInitialize();
      // Initializing the collection
      if (CollectionValue != null && CollectionValue.Length > 0)
        Collection = Deserialize(CollectionValue);
      else
        Collection = new ObservableCollection<int>();

      // Subscribing to events
      Collection.CollectionChanged += Collection_CollectionChanged;
      Session.Events.Persisting += Session_Persisting;
    }

    void Session_Persisting(object sender, EventArgs e)
    {
      if (!IsChanged)
        return;

      // Serializing the collection right before persist, if it is changed
      CollectionValue = Serialize(Collection);
      IsChanged = false;
    }

    void Collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
      IsChanged = true;
    }

So, what is going on here?
An instance of MyEntity is subscribed to a CollectionChanged event of MyEntity.Collection and updates MyEntity.IsChanged property when CollectionChanged event is fired. As the property is persistent, the MyEntity instance is added into a queue for persisting. Right before the persist procedure takes place, the instance of MyEntity receives a notification from its Session. During handling of this event we check whether the collection has been changed or not. If so, we update MyEntity.CollectionValue property and changes are successfully persisted to a database.

Note, that I've decided to use ObservableCollection type instead of List because the solution requires a notifications from the collection.

Hope this helps.

Thursday, January 13, 2011

Making connection strings secure

Recently, Paul Sinnema from Diartis AG asked on the support website how to make connection strings, listed in application configuration files (app.config or web.config), more secure.


For that time the only thing we could suggest was to use a workaround like that:

1. Encrypt the required connection string with encryption method you prefer and put it somewhere in web.config/app.config file in encrypted form.

2. Load DomainConfiguration through standard API:

var config = DomainConfiguration.Load("mydomain");

3. Set manually config.ConnectionInfo property with decrypted connection string

config.ConnectionInfo = new ConnectionInfo("sqlserver",
  DecryptMyConnectionString(encryptedConnectionString));

4. Build Domain with the config.

Paul answered that although the workaround is useful, he'd prefer that DataObjects.Net could be integrated somehow with standard .NET configuration subsystem that provides easy encrypting/decrypting of connection strings.

Let me explain the approach, Paul was talking about. For example, if plain connection string configuration looks like that;

  <connectionStrings>
     <add name="cn1" connectionString="Data Source=localhost\SQL2008;Initial Catalog=DO40-Tests;Integrated Security=True;MultipleActiveResultSets=True" />
  </connectionStrings>

then after executing "aspnet_regiis.exe -pef "connectionStrings" %PATH_TO_PROJECT%" the encrypted one will look like the following:

  <connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
      xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <KeyName>Rsa Key</KeyName>
          </KeyInfo>
          <CipherData>
            <CipherValue>TJETPde0GVrSAKk0VpUs3EsV8XFRQrVU1lGlrX8aEhvfa4MaMpN3O6KLo3I9e5oujXBImKtmXHWxnF6KRcSWteuQXD4I37Dq6yE1cZ4qDHqNMkcQK+lgi6jbRLcPzYQdFuOLagsAVpif8OvY0dJkiKd+Srqjwz7ZO225VCipaQs=</CipherValue>
          </CipherData>
        </EncryptedKey>
      </KeyInfo>
      <CipherData>
        <CipherValue>6bQyCUdH9rqdNAD4IwmSXtAQIEuRfSjpQ/Py5ovz2ZpwJdEXa4W3OKWMm52g1ARXPqMYw1thfQae//+1JWTAPQwrE3JTZEdcgu47KE2x8uqdWeJfoXSecp6berSPc4qAa4F2B5x8weUGPiAsBldVfBXwUBPniKWbnnXViJWmcSn16kaAtIkq5GtNOp7YhPt9WKZG0QkFRpEaRAWqLgxK6nXUwK8BgbGEBI4B27QSFj2ME1/JI+o//RrchntEuW6VolEA7PAejMujsIn1xb0hqg==</CipherValue>
      </CipherData>
    </EncryptedData>
  </connectionStrings>

As a result, the connection strings get encrypted and therefore, much more secure. Working with them is as simple as usual: they can be accesses through standard ConfigurationManager without any special tricks:

ConfigurationManager.ConnectionStrings["cn1"].ConnectionString
And this simplicity makes the whole approach extremely useful.

So, what could be done to get DataObjects.Net compatible with all this shiny stuff, keeping in mind that connection strings section is outside DataObjects.Net configuration?

After thinking for a while on the problem, we've got the following idea: what if we put in domain configuration not a connection string itself, but a reference to the connection string, that is actually defined in connectionStrings section? For instance:

<Xtensive.Orm>
    <domains>
      <domain provider="sqlserver" connectionString="#cn1" ... />
    </domain>
  </domains>
<Xtensive.Orm>
Where:
  • cn1 is a name of a connection string defined in connectionStrings section;
  • # sign is used to inform that actually this is a reference to a connection string and DataObjects.Net must resolve it through ConfigurationManager.
Having this feature implemented, DataObjects.Net will provide support for encrypted connection strings out-of-the-box.

And now, we'd like to ask you some important questions:
  • What would you say about the feature?
  • Will it be useful for you and should it be implemented?
  • Is the "#name" notation for setting a reference to a connection string is more or less clear or wouldn't it better to change it to something else?

Dear users of DataObjects.Net, we need your feedback. Please, post a comment or two.

Thanks in advance.