MongoDB MongoClient.GetServer() is Deprecated. What is the new API? - c#

This is my connection string to my database:
private static string ConnectionString = "mongodb://user:password#server:port/";
private static string AuthSource = "?authSource=location";
public static MongoCollection<ItemEntity> GetMyItemCollectionDB = new MongoClient(ConnectionString + DBName + AuthSource)
.GetServer().GetDatabase(DBName).GetCollection<ItemEntity>(CollectionName);
I heard that you can drop the getserver method:
public static MongoCollection<ItemEntity> GetMyItemCollectionDB = new MongoClient(ConnectionString + DBName + AuthSource)
.GetDatabase(DBName)
.GetCollection<ItemEntity>(CollectionName) as MongoCollection<ItemEntity>;
But for that, I get a "null object" error. What's the problem?
EDIT: If it is not that important to use the new API, then just tell me.

To get the MongoServer Instance, I de-compile assembly MongoDB.Driver.dll,
The function GetServer is
[Obsolete("Use the new API instead.")]
public static MongoServer GetServer(this MongoClient client)
{
return
MongoServer.Create(MongoServerSettings.FromClientSettings(client.Settings));
}
So you can try following code
MongoClient client = new MongoClient(ConnectionString + DBName + AuthSource);
MongoServer server = new MongoServer(MongoServerSettings.FromClientSettings(client.Settings));
var yourCollection = server.GetDatabase(DBName).GetCollection<ItemEntity>(CollectionName);
There're 4 ways in version 2.0.0+
MongoDB.Driver.MongoServer.Create(MongoServerSettings)
MongoDB.Driver.MongoServer.WithReadConcern(ReadConcern)
MongoDB.Driver.MongoServer.WithReadPreference(ReadPreference)
MongoDB.Driver.MongoServer.WithWriteConcern(WriteConcern)

I believe you know your second code at last returns an IMongoCollection<ItemEntity>
However, MongoCollection doesn't inherit from IMongoCollection, that's why you get a NULL value in the end.

Related

InsertMany json in string MongoDB

I would like to get collection via string and insert many json via string. How to do it? I don`t want to prepare object via C# class because my schema will change all the time and this is easy way.
code
const string connectionString = "mongodb://user:password#localhost:27017/myDB";
var client = new MongoClient(connectionString);
var db = client.GetDatabase("myDB");
var col = db.GetCollection("mycollection")
string insert = "[("Element1":"Test"),("Element2":"Test")]";
col.insertMany(insert);
my assemblies
MongoDB.Bson
MongoDB.Driver
MongoDB.Driver.Core
MongoDB.Libmongocrypt
ok. I found solution
public static async Task SaveToCollation(IMongoDatabase database, string collectionName, string json)
{
var collection = database.GetCollection<BsonDocument>(collectionName);
await collection.InsertOneAsync(BsonDocument.Parse(json));
}

Get connection string value from Microsoft.AspNetCore.TestHost.TestServer

I have a test project, i need to get the connection string value in a test class
public class EmplyeesScenarios
{
private readonly TestServer _testServer;
private readonly AppDbContext _testService;
public EmplyeesScenarios()
{
_testServer = TestServerFactory.CreateServer<TestsStartup>();
var dbOption = new DbContextOptionsBuilder<AppDbContext>()
.UseSqlServer("//here i need to put the same connection string of _testServer")
.Options;
_testService = new AppDbContext(dbOption);
}
}
You can use the service collection on your test host. For example:
var config = _testServer.Host.Services.GetRequiredService<IConfigurationRoot>();
var connectionString = config.GetConnectionString("Foo");
However, you should actually be using this for all your services, so instead of trying to new up your context at all, just do:
var context = _testServer.Host.Services.GetRequiredService<AppDbContext>();
No connection string needed.
Assuming that your test server is set up properly, you should just resolve your database context from the server instance directly. Like this:
_testServer = TestServerFactory.CreateServer<TestsStartup>();
// create service scope and retrieve database context
using (var scope = _testServer.Host.Services.CreateScope())
{
var db = scope.ServiceProvider.GetService<AppDbContext>();
// ensure that the db is created for example
await db.Database.EnsureCreatedAsync();
// add test fixtures or whatever
}
Technically, you could also resolve the configuration from the test host and the read the connection string out of it but since you are doing an integration test, you should actually test the full integration and not deviate from the existing setup by creating your database context manually.

Can You Use Variables This Way

This is my syntax, but it is not being passed to my connection string, it is being omitted, which of course is causing an error as the database doesn't exist. Is it possible to do this?
namespace bottomsup
{
class onetwothree
{
private static string databaseName = null;
private static string ServerConnectionString = "Data Source=BradJohnson;Initial Catalog=" + databaseName + "DB;User ID = pmartin;Integrated Security=True;MultipleActiveResultSets=True"";
Form1()
{
InitializeComponents();
}
private void ConnectToServerClick()
{
databaseName = textbox1.Text;
using (SqlConnection connection = new SqlConnection(ServerConnectionString))
{
connection.Open();
//more stuff
}
}
}
}
No, if you change the value of databaseName later on, it doesn't automatically change the value of ServerConnectionString.
You have to set the value of ServerConnectionString again yourself.
ServerConnectionString =
string.Format("Data Source=BradJohnson;Initial Catalog={0}DB;User ID = pmartin;Integrated Security=True;MultipleActiveResultSets=True", textbox1.Text);
I'd avoid the static variable, as it can lead to bugs if you try to reuse it, and especially if you overwrite it, in multiple places. One place sets it, then another, and now one or the other is going to grab an incorrect value when it tries to retrieve it.
Perhaps something like this instead, where you always have to pass the database name in:
private static string GetServerConnectionString(string databaseName)
{
return string.Format("Data Source=BradJohnson;Initial Catalog={0}DB;User ID = pmartin;Integrated Security=True;MultipleActiveResultSets=True", databaseName);
}
To use it with your existing code:
using (var connection = new SqlConnection(GetServerConnectionString(textbox1.Text)))
{
connection.Open();
//more stuff
}
I doubt if statics are justified in this case.
Nevertheless, it will not work with variable ServerConnectionString, but you could use a property instead:
private static string ServerConnectionString
{
get
{
return "Data Source=BradJohnson;Initial Catalog=" + databaseName +
"DB;User ID = pmartin;Integrated Security=True;MultipleActiveResultSets=True";
}
}
Often when you try to add a null value to something which has a value, it will fall over. In the DB Name you should use String.Empty as opposed to null.
Also I think you have an extra quote on the end of the string.
When you set the connection string, it is not going to dynamically update if you ever change the other property anyway.

HOW TO: dynamic connection string for entity framework

Like the title. How can I do it?
I tried something, but it doesn't work like I was expecting.
I'm using an Entity Framework model. I need to pass my connection string like parameter, so, in another file, I've written
namespace MyNamespace.Model
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class MyEntities: DbContext
{
public MyEntities(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
}
}
When I startup the app, I call this constructor in this way, so I can refer to this from anyway in the app:
public static MyEntities dbContext = new MyEntities(mdlImpostazioni.SetConnectionString());
where mdlImpostazioni.SetConnectionString() returns a string (the data are correct):
server=192.168.1.100\SVILUPPO;database=MyDB;uid=myName;pwd=111111;
When I execute this code, it seems to be all ok, but when I try to make a query like:
var query = (from r in MainWindow.dbContext.TabTipoSistema select r);
it throws an exception from here:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException(); //exception here
}
So, this is a bad way... which is the right one? (using only code C#, not from xaml)
Your approach is correct, but you need to remember the connection string for EF requires the metadata and so on. So use the EntityConnectionStringBuilder. For example:
// the model name in the app.config connection string (any model name - Model1?)
private static string GetConnectionString(string model, YourSettings settings)
{
// Build the provider connection string with configurable settings
var providerSB = new SqlConnectionStringBuilder
{
// You can also pass the sql connection string as a parameter instead of settings
InitialCatalog = settings.InitialCatalog,
DataSource = settings.DataSource,
UserID = settings.User,
Password = settings.Password
};
var efConnection = new EntityConnectionStringBuilder();
// or the config file based connection without provider connection string
// var efConnection = new EntityConnectionStringBuilder(#"metadata=res://*/model1.csdl|res://*/model1.ssdl|res://*/model1.msl;provider=System.Data.SqlClient;");
efConnection.Provider = "System.Data.SqlClient";
efConnection.ProviderConnectionString = providerSB.ConnectionString;
// based on whether you choose to supply the app.config connection string to the constructor
efConnection.Metadata = string.Format("res://*/Model.{0}.csdl|res://*/Model.{0}.ssdl|res://*/Model.{0}.msl", model); ;
return efConnection.ToString();
}
// Or just pass the connection string
private static string GetConnectionString(string model, string providerConnectionString)
{
var efConnection = new EntityConnectionStringBuilder();
// or the config file based connection without provider connection string
// var efConnection = new EntityConnectionStringBuilder(#"metadata=res://*/model1.csdl|res://*/model1.ssdl|res://*/model1.msl;provider=System.Data.SqlClient;");
efConnection.Provider = "System.Data.SqlClient";
efConnection.ProviderConnectionString = providerConnectionString;
// based on whether you choose to supply the app.config connection string to the constructor
efConnection.Metadata = string.Format("res://*/Model.{0}.csdl|res://*/Model.{0}.ssdl|res://*/Model.{0}.msl", model);
// Make sure the "res://*/..." matches what's already in your config file.
return efConnection.ToString();
}
EDIT
The exception you get is because when you pass a pure SQL connection string, it assumes you are working with Code first, so it calls the OnModelCreation event. When you include the MetaData section as shown above, that tells EF it's a complete EF connection string.
I believe the problem lies on the Datasource you specify. You need to add the port of the connection, e.g if your SQL Server is configured on Port 1433, try:
server=192.168.1.100,1433\SVILUPPO;database=MyDB;uid=myName;pwd=111111;
more details about connection strings you can find Here
Also I am not sure if uid and pwd are valid, better try User ID and Password:
Server=192.168.1.100,1433\SVILUPPO;Database=MyDB;User ID=myName;Password=111111;
Finally mind the case sensitivity.

Connect and check out methods

I have a method to connect to tfs and check out files. I have to separate it into 2 methods because they won't occur consecutively. But I am not sure how to separate it into 2 methods because if I did the check out, it means I have to get the Credentials and project collection again?
public static void Connect(String server, string path)
{
try
{
Uri serverUri = new Uri(server + "/tfs");
ICredentialsProvider credentials = new UICredentialsProvider();
TfsTeamProjectCollection tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(serverUri, credentials);
tpc.EnsureAuthenticated();
VersionControlServer versionControl = tpc.GetService<VersionControlServer>();
Workspace workspace = versionControl.TryGetWorkspace(path);
workspace.PendEdit(path);
}
I would suggest that you don't make the function static, then you can simply store the variables at class level (you can still store them at class level if they are static, but at least this way you have some scope as to the lifespan:
public class TfsWrapper
{
private TfsTeamProjectCollection tpc = null;
private VersionControlServer versionControl = null;
public TfsWrapper(string server, ...)
{
try
{
Uri serverUri = new Uri(server + "/tfs");
ICredentialsProvider credentials = new UICredentialsProvider();
tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(serverUri, credentials);
tpc.EnsureAuthenticated();
versionControl = tpc.GetService<VersionControlServer>();
}
}
public void Checkout(string path)
{
Workspace workspace = versionControl.TryGetWorkspace(path);
workspace.PendEdit(path);
}
I suggest you to use this code, he treats encapsulation & refactoring aspect between lot of servers & credentials
link : http://blogs.msdn.com/b/buckh/archive/2012/03/10/team-foundation-version-control-client-api-example-for-tfs-2010-and-newer.aspx

Categories

Resources