VS2012 DBML Changing Connection String - linq

I have a solution which contains multiple projects, such as a class library, websites, services, etc.
Projects such as the class library and service have a dbml connection to the same database. This means that the projects have connection strings such as:
MySolution.ClassLibrary.DatabaseA
MySolution.ClassLibrary.DatabaseB
MySolution.ClassLibrary.DatabaseC
MySolution.Service.DatabaseA
MySolution.Service.DatabaseD
This is a bit messy as I'm duplicating the connection strings. For integration purposes, I've also added another class library of shared components - which also has access to the same databases (Different tables). So I now have 3 instances of the same connection string in some places!
As mentioned, this is not only messy, but also leaves it open to bugs because if a connection string is missing from a website or service it will end up attempting to point at our development database (because it is defaulting to the setting from the class library).
What I would really like is simply to have a non or generically namespaced version of the connection string and just share it everywhere, e.g.
MySolution.ConnectionStrings.DatabaseA
MySolution.ConnectionStrings.DatabaseB
MySolution.ConnectionStrings.DatabaseC
MySolution.ConnectionStrings.DatabaseD
Then I would point each dbml at these connection strings and job done!
The problem is that VS2012 is so buggy when changing connection strings in the (right click > properties of the) dbml. It confuses itself between app or web.configs and Settings.settings - often when selecting DatabaseConnectingStringA, it will create a new one called DatabaseConnectionStringA1, which is very frustrating! It will also always add it's own namespace to connection strings when you add it through the project settings - which is required for the dbml.
Has anyone got a trick or method to get VS to do this?

In the end I did find a solution. It's not perfect, but it has reduced my connection strings from 7 or 8 (in certain places) down to 4 which I can copy and paste in between all projects for the various debug/release/staging builds.
Basically, for each DBML I added a partial class with a constructor which specifically uses my connection string:
partial class MyDataContext
{
public MyDataContext() : base(ConfigurationManager.ConnectionStrings["Master.DatabaseA"].ConnectionString)
{
OnCreated();
}
}
Then, after loading the DBML file where I could see all of the tables, I right clicked and chose properties in the background and changed the connection to None.
This has meant that the Web or App Config will look for a connection string of just "Master.DatabaseA" without referencing the project namespaces.
I then also cleared out the old connection strings in the other projects and it all works cleanly now. The only issue is that I need to set the connection back to None each time a new table or stored procedure is added. The project will not build in this situation so it can't accidentally be missed.

Related

Where can I find the database Room.DataBaseBuilder(...).build() creates?

I'm quite new to android and I am currently working on a app which should utilize a Room database. Following the documentation a room database can be created through the following lines:
myDatabase = Room.databaseBuilder(appContext, MyDatabase.class, "MyDB")
.build();
Now where did room create the database file?
It can't be found in my project folder.
The documentation doesn't mention anything about it and -generally speaking- barely gives any information about how this thing works.
Where is the database?
Does DatabaseBuilder.build() manage, to open the existing database created from previous app launches?
The list of questions is long.
Any information about the .build() thing aswell as further information about Room (misconceptions etc.) are very appreciated, for the documentation doesn't really make things clear for me.
Thank you!
Now where did room create the database file?
The database (a file) will be placed at the default location on the actual device which is data/data/<the_package_name>/database/MyDB.
In your case, as you have coded :-
myDatabase = Room.databaseBuilder(appContext, MyDatabase.class, "MyDB")
.build();
Then the database files will be: -
data/data/<your_package_name>/databases/MyDB
data/data/<your_package_name>/databases/MyDB-wal
data/data/<your_package_name>/databases/MyDB-shm
It can't be found in my project folder.
The database file is not part of the project, it is a file that is created and maintained on the actual device on which the App has been installed.
However, you can use Database Inspector (now App Inspection) on Android Studio to view the database e.g. :-
You can also view the files, if whatever device you test on allows access, by using Device File Explorer. e.g.
Does DatabaseBuilder.build() manage, to open the existing database created from previous app launches?
Yes, if the file exists then it is opened otherwise the file is created. If you uninstall the App this effectively delete's the file. The whole idea of a database is that it persists.
The build() undertakes various tasks, primarily seeing if the underlying file exists and then opening the file. In doing so it
extracts the version number that is stored in the file and compares the number against the number coded within the App (via the #Database).
If the version number from the App is greater then an attempt is tried to find a Migration (recently AutoMigration's have been added to Room).
compares the expected schema (according to the entities defined as part of the #Database), against what is found in the file.
A mismatch will result in the app crashing, so fixes would have to be made.
Note references to file is a simplification, by default Room uses a loggin mode called WAL (Write-Ahead Logging). In WAL mode there will be an additional 2 files that the SQLite routines maintain (you don't need to do anything):-
the database file name suffixed with -wal is the primary wal file into which changes are written (they are applied to the main database automatically).
the database file name suffixed with -shm (this is a WAL file for the WAL file).

talend - specify jndi as datasource

I have a talend job that uses tOracleInput component with connection type of ORACLE CUSTOM. It is working well.
Now, I have a requirement to use jndi as the database connection. Any ideas how can this be achieved?
First deploy your job as a webservice. After that you should be able to alter the Use or register a shared DB Connection in tOracleConnection. There you can define your JNDI datasource.
Source: https://www.talendforge.org/forum/viewtopic.php?pid=50374#p50374
The answer that I went with is creating my own custom talend component. Because deploying the talend job as a separate package than the actual web application is kind of, let's say, not an ideal solution in our case.
I have copied the tOracleInput component, and using Talend's component designer, I have added a "Use JNDI" checkbox and "JNDI name" textbox on the component. And modified the javajet files to build the connection from JNDI (InitialContext) using the JNDI name if the checkbox is checked. Else, proceed as usual on tOracleInput codes.
So, whenever I exported my talend job, I would tick the "Use JNDI" checkbox but if I'm just testing within Talend Studio, I would uncheck it and filled up the database properties will be used.
Hope this helps future readers.
Thanks!
**https://intodata.eu/tag/talend/
I have used the 3 part tutorials (on link above) on how to a build custom component to helped me start

SolrNet in CLR Stored Procedure

Has anyone ever used Solrnet inside CLR Stored Procedures? I would really appreciate pointers to some good tutorials.
One problem I'm facing is that I can't find a way to include the SolrNet library as a reference to the VS (2008) Database (SQL Server) Project.
Update:
So it seems that when you have an SQL Server Project, and you want to add a reference to a library, it has to first exist in SQL Server itself, which makes sense. This is done by creating an assembly in SQL Server from the DLL itself with the following SQL:
CREATE ASSEMBLY SolrNet FROM 'C:\CLR_SP\SolrNet.dll'
WITH PERMISSION_SET = UNSAFE
(Note that UNSAFE might have some repercussions on the security of the database however it is ok for me for now)
However the SolrNet.dll requires other library dependencies such as Castle.Windsor.dll (which in itself requires System.Core.dll) and Ninject.dll. I found the required version of Castle.Windsor.dll (which is 2.5.1.0) and also System.Core.Dll (which was in the .Net folder of Windows), however I cannot find the required version of Ninject.dll (which should be 2.1.0.76). I have attempted to create assembly version 2.2 but, as expected, it did not do the job.
I searched for it on different repositories but could not find it. Does anyone know where I could find this version of DLL?
Update 2:
So after lots of searching over the net, I still didn't manage to find Ninject.dll v2.1.0.76. My next attempt was to use the next version of SolrNet (which is v0.4.0.2002). This version required Ninject.dll v2.2 which I had already found. So my current status is registering all other libraries in SQL Server which are dependencies of SolrNet.dll. I will leave this open to document my process just in case there will be someone having the same problem.
Update 3:
I have managed to register all required libraries (some of which I got from SolrNet source on GitHub). So now, SolrNet is registered as an assembly in SQL Server, and therefore I can reference it from the .NET SQL Server Project (for creating the CLR Stored Procedure). So I have written a very simple CLR SP which connects to SOLR and retrieves a piece of data. Code below:
[Microsoft.SqlServer.Server.SqlProcedure]
public static void PrintToday()
{
SqlPipe p;
p = SqlContext.Pipe;
p.Send("Helloooo");
// Open Solr instance
SolrNet.Startup.Init<ActiveProduct>("http://192.168.2.190:8983/solr");
// Get instance of ActiveProduct
ISolrOperations<ActiveProduct> operations = ActiveProduct.GetActiveProductSolrOperations();
// Prepare QueryOptions. This will be passed as a parameter into the query() method.
SolrNet.Commands.Parameters.QueryOptions qo = new QueryOptions();
qo.Start = 0;
qo.Rows = 20;
// Query Solr
SolrQueryResults<ActiveProduct> results = operations.Query(new SolrQueryByField("SearchDescription", "pants"), qo);
// Read results
String s = "Docs found: " + results.NumFound;
p.Send(s);
}
My next problem is that when I deploy and run the CLR SP, an error is popping stating that Solr is already registered in container. The exact output that I see in SQL Server Management Studio is the following:
Helloooo
Msg 6522, Level 16, State 1, Procedure PrintToday, Line 0
A .NET Framework error occurred during execution of user defined routine or aggregate 'PrintToday':
System.ApplicationException: Key 'SolrNet.Impl.SolrConnection.CLRStoredProcedures2.ActiveProduct.SolrNet.Impl.SolrConnection' already registered in container
System.ApplicationException:
at SolrNet.Utils.Container.Register(String key, Type serviceType, Converter`2 factory)
at SolrNet.Utils.Container.Register[T](String key, Converter`2 factory)
at SolrNet.Startup.Init[T](ISolrConnection connection)
at SolrNet.Startup.Init[T](String serverURL)
at StoredProcedures.PrintToday()
PrintToday is the name of the CLR StoredProcedure
CLRStoredProcedures2 is the name of the .NET SQL Server project and default namespace in VS 2008
ActiveProduct is the name of the document in Solr, and the cs class with Solr annotations
As can be seen from the output, the first Pipe.send("Hellooo") is doing its job therefore the SP works fine until there.
When I searched for the above error, I found out that it will show when one tries to register Solr instance twice in the same application. Now I don't see where I am registering the instance twice. Am I missing something here?
Note that the above cs function worked fine when executed in a cs console application developed on my machine. Another detail which might be important is that the SOLR Server is being hosted on my machine which is on the same network of my SQL Server 2005.
Update 4:
For starters, the error I mentioned above (in update 3) does not fire when the SP is executed the 1st time just after deployment (let's assume that the 1st time works for now since I have another error which I'm currently working on fixing), the error fires when the SP is executed again afterwards. So it seems that whatever SolrNet.Startup.Init<ActiveProduct>("http://192.168.2.190:8983/solr"); is doing (creating some sort of session that has to do with a container I think) when called from the SP it is not releasing the "session" therefore the 2nd time (and each time afterwards) the SP is executed, the error is fired. Is there a way to sort of stop the session or releasing from the container. What I can do as a workaround is to try - catch the SolrNet.Startup.Init part, however this is not clean.
Thanks.
I'll try to summarize the steps / requirements with explanations whenever possible:
For some reason SQL Server seems to trigger the "hidden" dependencies of the merged SolrNet. Usually you can just use the merged SolrNet (which includes all integration modules) and if you ignore the integration classes the dependencies won't trigger. But in this case the unmerged SolrNet is necessary.
SolrNet does HTTP requests to the Solr server, so the DLL must be registered with UNSAFE permissions in SQL-CLR.
SolrNet Initialization (Startup.Init) must happen only once per application, but you don't have a 'root' context in SQL-CLR to place this initialization. A workaround is to use a singleton or a Lazy type. SQL-CLR doesn't run .NET 4 yet, but you can backport the Lazy type or use FSharp.Core.dll's implementation (I blogged about this some time ago)

Is there a way to suppress SQL03006 error in VS2010 database project?

First of all, I know that the error I am getting can be resolved by creating reference project (of type Database Server) and then referencing it in my Database project...
However, I find this to be overkill, especially for small teams where there is no specific role separation between developers and db admins..But, let's leave this discussion for another time... Same goes for DACs...Can't use DAC b/c of limited objects supported...
Question
Now, the question is: Can I (and how), disable SQL03006 error when building my Database project. In my case this error is generated because I am creating some users whose logins are "unresolved"...I think this should be possible I hope, since I "know" that logins will exist on the server before I deploy the script...I also don't want to maintain database server project just so I can keep refs resolved (I have nothing besides logins at server level)...
Workaround
Using pre/post deployment scripts, it is trivial to get the secript working...
Workaround Issue
You have to comment out user scripts (which use login references) for workaround...
As soon as you do that, the .sqlpermissions bomb out, saying there is no referenced users...And then you have to comment permissions out and put them in post deploy scripts...
The main disadvantage of this workaround is that you cannot leverage schema compare to its fullest extent (you have to specify to ignore users/logins/permissions)
So again, all I want is
1. to maintain only DB project (no references to DB Server projects)
2. disable/suppress SQL03006 error
3. be able to use schema compare in my DB project
Am I asking for impossible? :)
Cheers
P.S.
If someone is aware of better VS2010 database project templates/tools (for SQL Server 2008 R2) please do share...
There are two workarounds:
1.
Turn off any schema checking (Tools > Options > Database Tools > Schema Compare > SQL Server 200x, then the Object Type tab) for anything user or security related. This is a permanent fix
2.
Go through the schema comparison and mark anything user or security related as Skip and then generate your SQL compare script. This is a per schema comparison fix.
It should be obvious but if you already have scripts in your project that reference logins or roles then delete them and they won't get created.

sitecore proxy items published, still seem to have a link to the source

On the project I am working on, there are some proxy items that were added at some point from source location A to location B. However right now is not possible to check the source of the proxy and the proxy folder in B does not show anything that suggests that it's a proxy, besides the visual cue that it's grayed out.
When I analysed this article, I looked into the web.config and found this:
<proxiesEnabled>false</proxiesEnabled>
<publishVirtualItems>true</publishVirtualItems>
This seems to suggest that when the proxies were published they were published as regular items, losing any connection to their source, so since I want to recreate the proxies, due to some weird issues related to layout on the standard values item on the template not propagating correctly to the proxied items, I wanted to try to rename the old proxy folder and create a new one, however when I wanted to rename I got a modal alert with this message:
"This item occurs in other locations. If you rename it, the item will be renamed in the other locations as well. Are you sure you want to rename 'MyFoo'?"
Does this means the item still is attached to the source?
I am using Sitecore 6.2.0 (rev. 100701)
I suppose that the settings you mentioned are for master database. Now if you take a closer look at the article you reference, it lists 2 valid cases of proxies setup:
when web database also relies on proxies
when web database contains regular items only which came from publishing
These both cases assume that master database has proxiesEnabled='true'. Look, it doesn't have any sense otherwise - if proxies are disabled, the rest of the mechanism doesn't work, there are no virtual items.
And I can see proxiesEnabled='false' in the example you mentioned.
I'm not sure about the message you get. But if I need to change the proxy definition, I would do the following:
make sure proxiesEnabled='false' for web database (I guess this is your intention)
disable proxies for master database and change the proxies definition the way you want
set publishVirtualItems to true for master database
turn the proxies on for master database
make sure virtual items are in place and publish the site
Try this on some test environment and experiment to get the behavior you'd like - playing with the live site is a bad karma :)

Resources