LINQ to SQL over multiple databases - Failover Partner? - asp.net

I have an ASP.NET site using LINQ to SQL set up with multiple databases (by changing the Source for the tables on the other/"secondary" server). As seen here.
How do I set up a Failover Partner for this? I have it set up in the connection string, but I had to hardcode the Source with the server name, so that doesn't work.

The best method I could find/come up with was to create two LINQ External Mappings. On startup, I check to see if the main server is running using the main Mapping. If it's not, I set my connections to use the second LINQ mapping that has the FailOver database:
var xmlPath = #"C:\myAppFailOver.map";
System.Data.Linq.Mapping.XmlMappingSource linqMapping = System.Data.Linq.Mapping.XmlMappingSource.FromReader(System.Xml.XmlReader.Create(xmlPath));
using (DataClassesDataContext db = new DataClassesDataContext(connString, linqMapping))
{
//code
}

Related

Using Audit.NET SqlDataProvider with Azure SQL and Managed Identity

We are using the Audit.NET SqlServer Data Provider to store Audit logs in our Microsoft SQL Server. We are currently in the progress of migrating to the use of Azure SQL with Managed Identity to access the database. We haven't been able to get Audit.NET working with Azure SQL and the use of Managed Identity to connect to said database. The documentation doesn't provide any information on whether this functionality is supported or not.
We have managed to do this for our own database connections using Entity Framework Core by adding an Access Token to the SQL connection used by the Context like so:
SqlConnection sqlConnection = new SqlConnection(connectionString);
sqlConnection.AccessToken = new AzureServiceTokenProvider()
.GetAccessTokenAsync("https://database.windows.net/")
.Result;
This works perfectly fine. The issue we are running into is that we want to achieve the same with the Audit.NET Sql Data Provider. Due to the AuditContext being used by the SqlDataProvider being internal we are unable to pass an Access Token to the SqlConnection used.
The only solution we've come up with is writing our own Data Provider that is virtually the same as the SqlDataProvider, the only difference being that the Context used will set an Access Token on the SqlConnection. Is this the only viable solution here or does Audit.NET offer some other way to get it working with Azure SQL and Managed Identity?
I think the best way could be exposing an optional setting to provide the DbContextOptions where you can set an Interceptor like the one from here to set the AccessToken for the connection.
So you could initialize your configuration like this:
Audit.Core.Configuration.Setup()
.UseSqlServer(sql => sql
.ConnectionString("connection string")
.DbContextOptions(new DbContextOptionsBuilder()
.AddInterceptors(new AzureAuthenticationInterceptor(new AzureServiceTokenProvider()))
.Options));
or
Audit.Core.Configuration.Setup()
.UseSqlServer(sql => sql
.DbContextOptions(new DbContextOptionsBuilder()
.UseSqlServer("connection string")
.AddInterceptors(new AzureAuthenticationInterceptor(new AzureServiceTokenProvider()))
.Options));
UPDATE
The new DbContextOptions settings was added on version 16.2.1

Specifying default schema WebSpehere 8.5 Server

I am working on a migration project where we are migrating one application from Weblogic to Websphere 8.5 server.
In Weblogic server, we can specify default schema while creating datasource but I don't see same option in WebSpehere 8.5 server.
Is there any custom property through which we can set it , I tried currentSchema=MySchema but it did not work.
This answer requires significantly more work, but I'm including it because it's the designed solution to customize pretty much anything about a connection, including the schema. WebSphere Application Sever allows you to provide/extend a DataStoreHelper.
Knowledge Center document on providing a custom DataStoreHelper
In this case, you can extend com.ibm.websphere.rsadapter.Oracle11gDataStoreHelper.
JavaDoc for Oracle11gDataStoreHelper
The following methods will be of interest:
doConnectionSetup, which performs one-time initialization on a connection when it is first created
doConnectionCleanup, which resets connection state before returning it to the connection pool.
When you override doConnectionSetup, you are supplied with the newly created connection, upon which you can do,
super.doConnectionSetup(connection);
Statement stmt = connection.createStatement();
try {
stmt.execute(sqlToUpdateSchema);
} finally {
stmt.close();
}
doConnectionCleanup lets you account for the possibility that application code that is using the connection might switch the schema to something else. doConnectionCleanup gives you the opportunity to reset it. Again, you are supplied with a connection, upon which you can do,
super.doConnectionCleanup(connection);
Statement stmt = connection.createStatement();
try {
stmt.execute(sqlToUpdateSchema);
} finally {
stmt.close();
}
Note that in both cases, invoking the corresponding super class method is important to ensure you don't wipe out the database-specific initialization/cleanup code that WebSphere Application Server has built in based on the database.
As far as I know Weblogic only allows setting a default schema by setting the 'Init SQLto a SQL string which sets the current schema in the database, such asSQL ALTER SESSION SET CURRENT_SCHEMA=MySchema`. So, this answer is assuming the only way to set the current schema of a data source is via SQL.
In WebSphere, the closest thing to WebLogic's Init SQL is the preTestSQLString property on WebSphere.
The idea of the preTestSQLString property is that WebSphere will execute a very simple SQL statement to verify that you can connect to your database properly when the server is starting. Typically values for this property are really basic things like select 1 from dual', but since you can put in whatever SQL you want, you could setpreTestSQLStringtoSQL ALTER SESSION SET CURRENT_SCHEMA=MySchema`.
Steps from the WebSphere documentation (link):
In the administrative console, click Resources > JDBC providers.
Select a provider and click Data Sources under Additional properties.
Select a data source and click WebSphere Application Server data source properties under Additional properties.
Select the PreTest Connections check box.
Type a value for the PreTest Connection Retry Interval, which is measured in seconds. This property determines the frequency with which a new connection request is made after a pretest operation fails.
Type a valid SQL statement for the PreTest SQL String. Use a reliable SQL command, with minimal performance impact; this statement is processed each time a connection is obtained from the free pool.
For example, "select 1 from dual" in oracle or "SQL select 1" in SQL Server.
Universal Connection Pool (UCP) is a Java connection pool and the whitepaper "UCP with Webshere" shows how to set up UCP as a datasource.
for JDBC datasource, the steps are similar but, you can choose the default JDBC driver option.
Check out the paper for reference.

How to construct ConnectionStrings

Could you explain me how to construct correct ConnectionStrings? I mean that one you can find in web.config file in MVC project. I understand that if you want to add a new connection string you have to write <add ... /> XML tag with parameters such as name, connectionString (it is the most interesting parameter for me) and providerName (perhaps some else?). What each parameter does and means? How to construct connectionString parameter? Where is the db engine indicated?
The questions above are only examples. I care about collecting the most amount of information about constructing ConnectionStrings.
Starting from NET 2.0 you have at your disposal a class named SqlConnectionStringBuilder
Its purpose is to help building dynamically the connection string. But the various properties available explain in great detail the functionality underlying to each possible setting
The SqlConnectionStringBuilder class is derived by a base class named DbConnectionStringBuilder and this allows all the ADO.NET provider to implement their own version of this class. In the link provided there are the references relative to other ADO.NET providers
If you are trying to construct entity framework connection string just use as follows.It will help you..
string connectionString = new System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"]);
System.Data.SqlClient.SqlConnectionStringBuilder scsb = new System.Data.SqlClient.SqlConnectionStringBuilder(connectionString);
EntityConnectionStringBuilder ecb = new EntityConnectionStringBuilder();
ecb.Metadata = "res://*/Sample.csdl|res://*/Sample.ssdl|res://*/Sample.msl";
ecb.Provider = "System.Data.SqlClient";
ecb.ProviderConnectionString = scsb.ConnectionString;
UPDATED:
The easiest way to get the connection string is using the Server explorer window in Visual Studio (View-->Server Explorer menu) and connect to the server from that window. Then you can see the connection string in the properties of the connected server (F4 with your connection selected).
If you create the database in SQL Server Management Studio, that database will be created in a server instance, so that, to deploy your application you'll have to make a backup of the database and deploy it in the deployment SQL Server. Alternatively, you can use a data file using SQL Server Express (localDB in SQL Server 2012), that will be easily distributed with your app.
I.e. if it's an ASP.NET app, there's an App_Datafolder. If you right click it you can add a new element, which can be a SQL Server Database. This file will be on that folder, will work with SQL Express, and will be easy to deploy. You need SQL Express installed on your machine.

Constructing the Connection String for the DataContext Class

I see a couple of DataContext connection string questions. I'm going to try to differentiate this one a bit:
How does one construct a generic connection string to a database, localhost | User-PC\User | Some database... (it is hosted/managed by Microsoft SQL 2008)
I notice that it is IDisposable. So if I have multiple users hitting my site, my code can only access the database one instance at a time, and has to wait until each instance is disposed, in order for the data to be consistent for each user?
Is it possible, by any chance, to somehow enable LINQ in F#-Interactive, and connect to the database from there? I cannot figure out how to enable/load the System.Data dll into fsi. Maybe that is unique to my installation, or it is a common thread? (ie, my installation also does not recognize windows.base.dll--I have to manually get it from programs\reference assemblies).
Anyhow, I've pretty much conclusively discovered that
let x = new System.Data.Linq.DataContext("localhost")
...does not work.
1) How does one construct a generic connection string to a database?
There is no generic way to construct a connection string. The best thing to do is to keep the connection string in some configuration file where you can change it depending on your configuration (the name of SQL Server machine, authentication options, whether it is a file-based database or normal). There is a web site with examples for most of the options.
2) I notice that it is IDisposable. So if I have multiple users hitting my site, my code can only access the database one instance at a time [...]?
No, this is not how DataContext works. The DataContext does not keep a live connection to the server that would block anybody else from using the SQL server. It keeps some state (i.e. cached entities that were already obtained) and it uses optimistic concurrency to make sure that the state is consistent (you can use transactions to prevent other connections, if that's what you want).
3) Is it possible, by any chance, to somehow enable LINQ in F#-Interactive [...]?
That shouldn't be a problem. You can reference assemblies using #r "foo.dll" in F# interactive. The typical approach for F# 2.0 is to generate the data context using C# tools and then just reference it (for F# 3.0, things are easier because you can just use type provider).
If you generate LINQ to SQL data context for Northwind in C#, the F# Interactive use would look like this:
#r #"<whatever_path>\Northwind.dll"
#r "System.Data.Linq.dll"
open Northwind
open Microsoft.FSharp.Linq
let connStr = #"Data Source=.\SQLEXPRESS;AttachDbFilename=<path>\NORTHWND.MDF;" +
#"Integrated Security=True;User Instance=True"
let operation () =
// Using 'use' to make sure it gets disposed at the end
use db = new NorthwindDataContext(connStr)
// do something with the database
There actually is a somewhat generic way to construct a connection string:
open System.Data.Common
open System.Data.SqlClient
let providerName = "System.Data.SqlClient"
let factory = DbProviderFactories.GetFactory(providerName)
let cnBuilder = factory.CreateConnectionStringBuilder() :?> SqlConnectionStringBuilder
cnBuilder.DataSource <- "localhost"
cnBuilder.InitialCatalog <- "MyDatabase"
cnBuilder.IntegratedSecurity <- true
let connStr = cnBuilder.ConnectionString
My approach was to have 1 connection string and then use that for all of my DataContext connections. So this code builds the EntityConnectionString based on MyConnString:
protected override MyEntities CreateObjectContext()
{
string ConnString =ConfigurationManager.ConnectionStrings["MyConnString"];
string seConn = ConfigurationManager.ConnectionStrings["MyEntities"].ToString();
EntityConnectionStringBuilder ecsb = new EntityConnectionStringBuilder(seConn);
ecsb.ProviderConnectionString = ConnString;
EntityConnection ec = new EntityConnection(ecsb.ToString());
ScheduleEntities ctx = new ScheduleEntities(ec);
return ctx;
}

FoxPro Database and asp.net

I have a website that uses asp.net 3.5 and Sql server 2008 as backend data store . now we want to add a new page to our website . but the data that we want to share in this page is already being created and saved by a FoxPro software in one of our local systems.
I've no experience in FoxPro . is there any way to use this data in our site ? specially without being have to create a new database in server and importing or writing all records all over again ? what is the best way in such a situation ?
by the way , is it possible to change the extension of a FoxPro database or not ? something like Database.customExt ?
You can connect to a FoxPro database using an OLEDB datasource in ADO.NET. It's up to you whether you feel the need to import the data into SQL Server or just access it directly in FoxPro. It would depend on whether you want to join the data with the SQL Server data in queries for one thing.
In addition to the answers that you already got. You might be interested in using LINQ to VFP or VFP Entity Framwork Provider to make the data access even easier by using LINQ.
You could create a linked server to this Foxpro Database.
Also, Foxpro tables can have any extension. However, you'll have to specify the extension when using the table or database. For Example:
OPEN DATABASE MyFoxProDatabase.customExt
USE mytable.custonExt
You have several options for structuring your data access to FoxPro. You can put the ADO.NET data access code in the codebehind, in it's own c# library or use the objectdatasource for 2 way binding.
private void LoadData(string parameter)
{
string sql = "SELECT a.myfield FROM mytable.customExt a WHERE a.whereField=?";
using(OleDbConnection conn = new OleDbConnection(myConnectionString))
{
using (OleDbCommand command = new OleDbCommand(sql, conn))
{
command.Parameters.AddWithValue("#Parameter", parameter);
try
{
conn.Open();
using(OleDbDataReader dr = command.ExecuteReader(CommandBehavior.CloseConnection))
{
myGridView.DataSource = dr;
myGridView.DataBind();
}
}
catch (Exception ex)
{
throw;
}
}
}
}
Here is a sample connection string to use in web.config:
<add name="myData" connectionString="Provider=VFPOLEDB.1;Data Source=C:\MyFiles\" providerName="System.Data.OleDb"/>
I belive ou can use a custom extension to your FoxPro tables and databases. All your SQL statements would then need to explicitly use that extension.
SELECT t.MyField FROM MyTable.customExt t
While you can change the extension for a Visual FoxPro table, that only affects the DBF file. If the table has any memo fields, there's an associated FPT file, for which you can't change the extension. Similarly, if the table has an associated index file, it must have a CDX extension.
So, if the reason you want to change the extension is to allow multiple tables with the same filestem, don't. It's a good way to really mess things up.

Resources