Print Page | Close Window

Side effects of implementing IDataSourceKeyResolver

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2009
Forum Discription: For .NET 3.5
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=3510
Printed Date: 17-Jul-2019 at 8:33am


Topic: Side effects of implementing IDataSourceKeyResolver
Posted By: stevenr
Subject: Side effects of implementing IDataSourceKeyResolver
Date Posted: 27-Jun-2012 at 7:08am
For my application I was worried about leaving the database connection string essentially in plain text, so I implemented IDataSourceKeyResolver from the instructions given in the documentation. In the IdeaBlade.ibconfig file I added a top-level probeAssemblyName node and pointed it to AppHelper. I also encrypted the connection string in IdeaBlade.ibconfig.
In my AppHelper project I implemented the IDataSourceKeyResolver interface in a particular way so that I can decrypt the encrypted connection string. This works entirely as expected.
 
However, this led to an entirely unintended side effect. As it turned out, when calling the Create method of some entity that relies on GenerateId, I get the exception:
 
No class implementing IdeaBlade.Persistence.IIdGenerator was found. If this class does exist then you may need to add an <ProbeAssemblyName> node to IdeaBlade.ibconfig file.
 
It does not say in the documentation that when implementing IDataSourceKeyResolver, you must also implement IIdGenerator; in reality this turned out different. So my question is: when implementing IDataSourceKeyResolver, are there other interfaces that also need to be implemented? I would rather not find out one by one from the end users encountering exceptions which additional functionality is essentially overriden with nothing by this one seemingly unrelated change.



Replies:
Posted By: kimj
Date Posted: 27-Jun-2012 at 7:44am
Implementing a custom IDataSourceKeyResolver does not mean that you must implement other interfaces such as the IIdGenerator.
Two things to check -
 
1) DevForce does application-wide vs. RdbKey probing depending on what it's looking for, and you still need need an RdbKey in your ibconfig file to provide probe assemblies, but without the DB connection information. Something like this:
 
<rdbKey name="default">
<probeAssemblyName>Model</probeAssemblyName>
</rdbKey>
 
2) Also make sure that you do not change the RdbKey name in the key returned from your GetKey implementation in the custom resolver. All entities have a DataSourceKeyName property which is set during code generation via the Object Mapper, and at run time DevForce will expect to resolve an RdbKey with this key name.


Posted By: stevenr
Date Posted: 27-Jun-2012 at 12:20pm
I doublechecked and the code complies with both of these points. I kept the rdbKey node in the ibconfig; here is a snippet:
<ideaBlade xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance - http://www.w3.org/2001/XMLSchema-instance " xmlns:xsd=" http://www.w3.org/2001/XMLSchema - http://www.w3.org/2001/XMLSchema " version="1.07">
  <probeAssemblyName>AppHelper</probeAssemblyName>
...
  <rdbKey name="default" databaseProduct="Unknown">   
    <connection>MyEncryptedConnectionString</connection>
    <probeAssemblyName>MyModelAssembly</probeAssemblyName>
  </rdbKey>

The only thing I changed in the ibconfig was to substitute the <connection> node with its encrypted value. My implementation of GetKey then decrypts it. Everything else in this file is exactly the way it was generated.

As for the RdbKey name in my implementation of GetKey, I don't change that either; in fact, I don't use either parameter, I defined a string constant with the value "default" and just return that as the key name.
 
One thing I did notice was that my implementation of GetKey is called twice. Could that perhaps be causing the problem I'm seeing? I designed the encryption/decryption as separate library so that other applications can use it.
To obtain the encrypted connection string, the separate library loads the same AppModel.dll assembly and then extracts the <ideaBlade> resource back from the AppModel.dll, whose connection node is then decrypted. I don't know if this is the ideal way to do this, but it certainly gets me what I need because the AppModel.dll already contains the encrypted connection string that I need and I figured I would just reuse that rather than creating yet another place to hold the connection string.



Posted By: kimj
Date Posted: 27-Jun-2012 at 1:08pm
Since you're calling GenerateId yet don't have a custom IIdGenerator I assume you're using SQL Server identity columns for your keys.  If not, then calling GenerateId can result in an error.
 
In order for the built-in SqlServerIdGenerator to be used the RdbKey must be recognized as being for the SqlServer "DatabaseProduct".  You can pass this into the RdbKey construct to ensure that DevForce knows to use this generator.
 
GetKey will be called twice, unfortunately.  DevForce resolves the key both on a logical "client" side and "server" side, even when you're not running an n-tier application. 


Posted By: stevenr
Date Posted: 28-Jun-2012 at 5:22am
Passing in SqlServer as the DatabaseProduct did not resolve this issue. I am actually using different types of authentication for various build configurations and am seeing the issue with both integrated and Sql Server authentication. Simply returning a hardcoded connection string in my GetKey implementation also gave the same error, so it does not appear to have anything to do with how I'm obtaining the actual value of the connection string.
I ended up including the built-in implementation of IIdGenerator in NumericIdGenerator.cs in the AppHelper project and this appears to work now.


Posted By: stevenr
Date Posted: 28-Jun-2012 at 5:51am
Scratch that.  If I pass in "System.Data.SqlClient" as the data provider parameter in the RdbKey constructor and then use the exact same syntax for the connection string as SQL Server expects, then this works flawlessly.


Posted By: kimj
Date Posted: 28-Jun-2012 at 10:30am
Glad you got it working, Steven.


Posted By: toddgleason
Date Posted: 26-Apr-2013 at 7:56am
We had this exception when trying to save objects for a newly-created table, and it turned out that, while the ORM looked fine to us, the table definition was missing the Identity attribute for the primary key column. Once we fixed this in SQL Server Management Studio, re-ran the ORM, and rebuilt the solution, the problem went away.



Print Page | Close Window