I´m using Entity Framework (latest Version) with the Oracle Driver (latest Version) in an ASP.NET MVC 5 Application. I want to set the connection string for my model during runtime, but every time I do it receives the data from the table that I used to create the model. It´s the same when I change the connection string in the web.config. Does anybody know why it behaves this way?
this is how i create the connection string:
public static string CreateConnectionString(string userName, string service)
{
const string providerName = "Oracle.ManagedDataAccess.Client";
OracleConnectionStringBuilder oraBuilder = new OracleConnectionStringBuilder();
oraBuilder.DataSource = service + ":1521/" + service;
oraBuilder.UserID = userName;
oraBuilder.Password ="xxx";
oraBuilder.PersistSecurityInfo = true;
EntityConnectionStringBuilder efBuilder = new EntityConnectionStringBuilder();
efBuilder.Metadata = "res://*/Model2.csdl|res://*/Model2.ssdl|res://*/Model2.msl";
efBuilder.Provider = providerName;
efBuilder.ProviderConnectionString = oraBuilder.ConnectionString;
return efBuilder.ConnectionString;
}
this is the overload of the model´s constructor:
public Entities(string connectionString)
: base(connectionString)
{
}
this ist my connection string:
try this connection string:
<connectionStrings>
<add name="VoccDbContext" connectionString="metadata=res://*/Entities.Vocc.VoccModel.csdl|res://*/Entities.Vocc.VoccModel.ssdl|
res://*/Entities.Vocc.VoccModel.msl;provider=Oracle.DataAccess.Client;provider connection string="DATA SOURCE=sameDbName;PASSWORD=somePass;USER ID=someUser;""providerName="System.Data.EntityClient" />
</connectionStrings>
DIRECTORY_SERVERS=(tnsnames.somesite.org:389:636)
DEFAULT_ADMIN_CONTEXT="dc=site,dc=com"
DIRECTORY_SERVER_TYPE=OID
here( LDAP.ORA file) to be modified with correct LDAP Parameters
Do not edit XXXModels.cs. Try to edit XXXModels.Context.tt.
Add following code after public <#=code.Escape(container)#>()...}
public <#=code.Escape(container)#>(string connectionString)
: base(connectionString)
{
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
this.Configuration.LazyLoadingEnabled = false;
<#
}
foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
{
// Note: the DbSet members are defined below such that the getter and
// setter always have the same accessibility as the DbSet definition
if (Accessibility.ForReadOnlyProperty(entitySet) != "public")
{
#>
<#=codeStringGenerator.DbSetInitializer(entitySet)#>
<#
}
}
#>
}
Related
I have a service inside an azure function
public MyService(
IConfigurationProvider configurationProvider,
ISerializationHelperService serializationHelperService,
ICommandListBuilder commandListBuilder,
[CosmosDB(
StaticSettings.Db,
StaticSettings.MyCollection.Collection,
ConnectionStringSetting = StaticSettings.DbConnectionStringSetting)] IDocumentClient documentClient)
{
//my logic here - this does get hit
}
My service is instantiated however, documentClient is null
How can I get this to be set properly? I dont get any errors
I have checked and there are no issues with the connection settings
public const string Db = "mydbname";
public const string DbConnectionStringSetting = "CosmosDBConnection";
public static class MyCollection
{
public const string Collection = "mycollectionname";
public static Uri CollectionUri => UriFactory.CreateDocumentCollectionUri(Db, Collection);
}
I am using a Startup class with an AddServices method to setup DI
Do I need to put something in there?
Paul
I have Azure function v2 project and I'm able to inject all my dependencies. Below lines added for IDocumentClient
string databaseEndPoint = Environment.GetEnvironmentVariable("DatabaseEndPoint");
string databaseKey = Environment.GetEnvironmentVariable("DatabaseKey");
builder.Services.AddSingleton<IDocumentClient>(new DocumentClient(new System.Uri(databaseEndPoint), databaseKey,
new ConnectionPolicy
{
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp,
RequestTimeout = TimeSpan.FromMinutes(5),//Groupasset sync has some timeout issue with large payload
// Customize retry options for Throttled requests
RetryOptions = new RetryOptions()
{
MaxRetryAttemptsOnThrottledRequests = 5,
MaxRetryWaitTimeInSeconds = 60
}
}
));
My Database Service
protected readonly IDocumentClient client;
protected BaseDao(IDocumentClient client)
{
this.client = client;
}
hope it will help!
Problem:
I have webapi serviss where almost every user has its own database instance to connect. So i have to set different connection string for each user. To recognize user i will pass specific Token into header. Regarding on this Token, system has to build and set differenct connection string into Data Access layer constructor (Order in this case)
Question:
Is it possible to pass argument to Ninject or any kind of IoC binder regarding on request header?
IOrders _orders;
public HomeController(IOrders order)
{
_orders = order;
}
Here is an Ninject binding, but as you can guess, HttpContext.Current is null.
private static void RegisterServices(IKernel kernel)
{
var some_value = HttpContext.Current.Request.Headers.GetValues("Token");
kernel.Bind<IOrders>()
.To<Orders>()
.WhenInjectedInto<HomeController>()
.WithConstructorArgument("Token", some_value);
}
Maybe there is much elegant way to do this using Controller Factory ?
I would create a service class that does this lookup for you. then inject this service into the Orders implementation.
public interface IRequestContext {
string ConnectionString {get;}
}
public class HttpHeaderRequestContext : IRequestContext {
public string ConnectionString {
get {
var token = HttpContext.Current.Request.Headers.GetValues("Token");
// .. lookup conn string based on token
}
}
}
public class Orders : IOrders {
public Orders(IRequestContext ctx) {
// create new connection w/ ctx.ConnectionString
}
}
using this method, the lookup of headers and connection strings is abstracted away from the implementation. this makes it easier to test and easier swap out with a different method of obtaining a connection string if the need arises.
After implementing Dave approach, i realized that i could solve this connection string injection by feeding HttpContext.Current into Ninject binding like this:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IOrders>()
.To<Orders>()
.WhenInjectedInto<HomeController>()
.WithConstructorArgument("smth", x => {
var token = HttpContext.Current.Request.Headers.Get("Token");
var _db = new SomeDataCxt();
var connStr = _db.DbStringRepository.GetByToken(token);
return connStr;
});
}
In my MVC Application I use the connection string is set in the Web.config via
Private connectionString As String = ConfigurationManager.ConnectionStrings("DBCS").ConnectionString
and have no problems with my db connection. But since I need a password and username to log into my database I hardcoded that in the web.config
<connectionStrings>
<add name="DBCS" connectionString="server=win\SQLExpress;database=myDb; uid=myUsername;password=myPassword" providerName="System.Data.SqlClient" />
</connectionStrings>
I am looking for a way to send the password and username from the userinterface to the config.web file first off I thought the ConfigurationManager Class should provide a property for that but I cannot find something. Can anyone explain to me how to do this?
You can save this value in app settings:
<appSettings>
<add key="DBCS" value="Data Source=win\SQLExpress;Initial Catalog=myDb;User ID={0};Password={1}" />
</appSettings>
and then do the following:
using System.Data.SqlClient;
public void DoDatabaseOperations(string _Username, string _Password)
{
string connetionString = null;
SqlConnection cnn ;
connetionString = string.Format(ConfigurationManager.AppSettings("DBCS"), _Username, _Password);
cnn = new SqlConnection(connetionString);
try
{
cnn.Open();
// your code here
cnn.Close();
}
catch (Exception ex)
{
// handle exception
}
}
VB.NET Equivalent:
Imports System.Data.SqlClient
Public Sub DoDatabaseOperations(_Username As String, _Password As String)
Dim connetionString As String = Nothing
Dim cnn As SqlConnection
connetionString = String.Format(ConfigurationManager.AppSettings("DBCS"), _Username, _Password)
cnn = New SqlConnection(connetionString)
Try
cnn.Open()
' your code here
cnn.Close()
' handle exception
Catch ex As Exception
End Try
End Sub
I have Entity Framework TaskTracker.edmx
There is StoredProcedure GetEmployees and used Complex type to return the Data
at TaskTrackerDataService.cs
public static void InitializeService(DataServiceConfiguration config)
{
// Grant only the rights needed to support the client application.
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
[WebGet, WebInvoke(ResponseFormat = WebMessageFormat.Xml)]
public IQueryable<TaskTracker_EDM.EmployeeView> GetEmployees()
{
TaskTracker_EDM.TaskTrackerEntities ctx = new TaskTracker_EDM.TaskTrackerEntities();
return ctx.GetEmployees(string.Empty).AsQueryable();
}
at Client Site [Console Application]
var emps = ctxDSvc.Execute<EmployeeView>(new Uri("http://localhost:2402/TaskTrackerDataService.svc/GetEmployees", UriKind.RelativeOrAbsolute));
foreach (EmployeeView e in emps)
{
Console.WriteLine(string.Format("ID: {0} - {1} ", e.EmployeeID, e.Name));
}
foreach is not working, There is no data in emps.
always emps has
+ emps {System.Data.Services.Client.QueryOperationResponse<TaskTrackerConsoleTest.TaskTrackerDataService.EmployeeView>}
System.Collections.Generic.IEnumerable<TaskTrackerConsoleTest.TaskTrackerDataService.EmployeeView> {System.Data.Services.Client.QueryOperationResponse<TaskTrackerConsoleTest.TaskTrackerDataService.EmployeeView>}
I read that OData doesn't support Complex Type.[Did they fix it] or are there another solution.
Some said, use a Xml to Linq kind of approach to get the complex types. [any help]
Any help or advice.
I Serialize the result [ObjectToString] at the Server before send it to the Client application
then Deserialize it.
If there are other ideas, please don't hesitate to tell me.
1- at TaskTracker_WCF1 -> TaskTrackerData.cs
//When StoredProcedure return Complex Type , Then you need to serialise it [Object To String] before send it to Client application
//OData doesn't support Complex Type
[WebGet]
public String GetEmployees_SPreturnComplexType(String nameSearch)
{
TaskTracker_EDM.TaskTrackerEntities ctx = new TaskTracker_EDM.TaskTrackerEntities();
List<TaskTracker_EDM.EmployeeView> hiEmployeeView = (List<TaskTracker_EDM.EmployeeView>)ctx.GetEmployees("Keko88").ToList();
//Serialize object to String
XmlSerializer serializer = new XmlSerializer(hiEmployeeView.GetType());
using (StringWriter writer = new StringWriter())
{
serializer.Serialize(writer,hiEmployeeView);
return writer.ToString();
}
}
2- at Console application at program.cs
TaskTrackerDataService.TaskTrackerEntities ctxDSvc =
new TaskTrackerDataService.TaskTrackerEntities(new Uri("http://localhost:2402/TaskTrackerDataService.svc"));
//=======================================
//2-1Call StoredProcedure return Complex Type
String emps = ctxDSvc.Execute<String>(new Uri(ctxDSvc.BaseUri.ToString() +
"/GetEmployees_SPreturnComplexType", UriKind.RelativeOrAbsolute)).Single();
//2-2We need to Deserialize it before use it
var reader = new StringReader(emps);
var serializer = new XmlSerializer(typeof(List<EmployeeView>));
List<EmployeeView> instance = (List<EmployeeView>)serializer.Deserialize(reader);
//=======================================
foreach (EmployeeView e in instance)
{
Console.WriteLine(string.Format("ID: {0} - {1} ", e.EmployeeID, e.Name));
}
Console.WriteLine();
//=======================================
In C#, MVC code first application I have
public class CarContext : DbContext { }
class in first version of application. And connection string is like
<add name="CarContext" providerName="System.Data.SqlClient" Integrated Security=true;
connectionString="Data Source=Dragon; Initial Catalog=CarDBv1;"/>
When I run application, first version of database is created - CarDBv1.
Then I edit my CarContext class, for example, add new table, change any property etc., also change version of application, change connection string
Initial Catalog=CarDBv1; to Initial Catalog=CarDBv2; and run project. In this case I have 2 database: CarDBv1 and CarDBv2. But, CarContext class is same in applications.
Now, I need to connect both database and their context(CarContext) from any console application and use their tables for converting, reading etc.
I found a similar answer here: https://stackoverflow.com/a/16860878/1534785
But in my applications context name is same.
How can I create 2 instances for every CarContext in applications by their database connection string?
You can use an overloaded constructor to DbContext to allow contexts to point at and arbitrary database which is NOT declared in app.config.
See the constructor with dbConnection.
public class MyDbContext : DbContext, IContextOptions {
//ctors
protected BosBaseDbContext(string connectionName)
: base(connectionName) { }
protected BosBaseDbContext(DbConnection dbConnection, bool contextOwnsConnection)
: base(dbConnection, contextOwnsConnection) { }
}
usage
//datasource could be localhost, DBName the catalog name
new MyDbContext((GetSqlConn4DbName(dataSource,dbName )),true);
public DbConnection GetSqlConn4DbName(string dataSource, string dbName) {
var sqlConnStringBuilder = new SqlConnectionStringBuilder();
sqlConnStringBuilder.DataSource = String.IsNullOrEmpty(dataSource) ? DefaultDataSource : dataSource;
sqlConnStringBuilder.IntegratedSecurity = true;
sqlConnStringBuilder.MultipleActiveResultSets = true;
var sqlConnFact = new SqlConnectionFactory(sqlConnStringBuilder.ConnectionString);
var sqlConn = sqlConnFact.CreateConnection(dbName);
return sqlConn;
}