multiple Mongo database and spring-data [duplicate] - spring-data-mongodb

This question already has answers here:
Spring-data-mongodb connect to multiple databases in one Mongo instance
(7 answers)
Closed 4 years ago.
I am in the process of finding out how do I dynamically connect to different mongo db's based on the user that logs in. I see multiple posts that talks about it but since I am new to this just wanted to understand more on how to implement it. In our application while creating the user account we could create different db files based on the userName, which acts as a key.
So we know which database to connect so it is just matter of selecting correct Factory I guess.
I see following constructor in the template code.
public MongoTemplate(Mongo mongo, String databaseName) {
this(new SimpleMongoDbFactory(mongo, databaseName), null);
}
My current Spring java config does following
#Bean
public MongoDbFactory mongoDbFactory() throws Exception {
UserCredentials userCredentials =
new UserCredentials(
env.getRequiredProperty(databasePropertyNames.getDBUsernamePropertyName()),
env.getRequiredProperty(databasePropertyNames.getDBPasswordPropertyName()));
return new SimpleMongoDbFactory(mongo().getObject(),
env.getRequiredProperty(databasePropertyNames.getDBNamePropertyName()),
userCredentials);
}
#Bean
public MongoTemplate mongoTemplate() throws Exception {
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
mongoTemplate.setWriteConcern(WriteConcern.SAFE);
return mongoTemplate;
}
Questions:-
1.Will there be multiple SimpleMongoDbFactory objects that I need to create based on the user that logged in?
If yes then how do I do it and do I need to maintain that object Map?
2. How would I do set those in mongoTemplate at runtime?
Your help would be highly appreciated:)

Following posts worked well for me
github.com/Loki-Afro/multi-tenant-spring-mongodb
Spring-data-mongodb connect to multiple databases in one Mongo instance
Along with this one has to update the Mongo instance to allow the user from default database to be able to write in to any other database

Related

Migrate a laravel project with a single database to multiple bases

I would have to make many modifications to be able to transfer my laravel project with a single database that has many query builders and eloquent to a project that supports more than one database?
I understand that once a new database is installed it is necessary to use:
connection('mysql2')
When consulting a database, do we tend to change the whole project with this sentence? specifying the connection in each place?
You can add a $connection property to your Eloquent models to specify the database connection there. This way you don't need to update your queries.
protected $connection = 'connection-name';
Migration with multiple connections
public function up()
{
Schema::connection('mysql-2')->create('user_details', function (Blueprint $table) {
//........
});
}
public function down()
{
Schema::connection('mysql-2')->dropIfExists('user_details');
}
Handle Relationship with multiple database connections
UserDetail.php //mysql-2 (connection-2)
class UserDetail extends Model
{
protected $connection = 'mysql-2';
public function user()
{
return $this->setConnection('mysql')
->belongsTo(User::class);
}
}
User.php //mysql (connection-1) //default connection
class User extends Model
{
//with default connection
public function detail()
{
return $this->setConnection('mysql-2')
->hasOne(UserDetail::class);
}
}
You don't need to a specified connection in a controller for retrieving/delete/insert data
I Understand that you are asking basically how to change database.
For whole project: you can edit mysql connection details in your .env file.
You can also use 2 databases with 1 project , you can learn how to do that from this question which has been already answered: How to use multiple databases in Laravel
I am sorry if i didn't understand your question.
Let me know if it helps you.

Entity Framework not creating Tables

I really have no luck with the EF every time. This time it looks like this:
First time i created a context i had an error like:
Invalid object name 'dbo.TableName1'
After this setting the Database Initializer to CreateDatabaseIfNotExists T it did the trick.
Next i created a different context, which was changed at some point of the development. So this time i keep getting this error:
The model backing the 'NewContext' context has changed since the database was created.
I found a solution to set the Database Initializer to null, but after this i keep getting the first error:
Invalid object name 'dbo.TableName2'
I also tried to set the the initializer to DropCreateDatabaseIfModelChanges and DropCreateDatabaseAlways, and these settings throw the exception:
Cannot drop database "DatbaseName" because it is currently in use
I think I already tried everything i found on the Web (there are many topics of this kind) but none helped me with it.
Dropping the Database didn't help, nor changing from Local File Database to SQL Server 2014 Exspress. The same exception is thrown. Any ideas?
Edit1:
Working context:
public class ProfilesContext : DbContext
{
public ProfilesContext() : base("DefaultConnection")
{
}
public DbSet<Profile> Profiles { get; set; }
public DbSet<PrevilegedContact> PrevilegedContacts { get; set; }
}
Failing context:
public class PlacesContext : DbContext
{
public PlacesContext()
: base("DefaultConnection")
{
}
public DbSet<Place> Places { get; set; }
public DbSet<Price> Prices { get; set; }
public DbSet<Photo> Photos { get; set; }
public DbSet<Comment> Comments { get; set; }
}
For what you are doing, it seems you have 2 options for your initializer. There is Migrations and there is DropCreateDatabaseIfModelChanges.
Migrations will give control over updating the database tables when your models change and allow you to preserve data. You can configure it to allow data loss or not. Very useful during development time if you already have test data in there.
DropCreateDatabaseIfModelChanges will simply drop the database each time you make model changes and recreate it with the new schemas.
You are getting the error message
Cannot drop database "DatbaseName" because it is currently in use
because you have more than likely browsed the table in your server explorer and have an open connection to the database. You can close the connection using the right click context menu in server explorer.
If you want a video overview on Migrations there is a free video by Scott Allen & Pluralsight. This is MVC4 but the Entity Framework section does cover Initalizers. If you want an updated one for MVC5 to include multiple Contexts etc, it does exist but you would need to take the Pluralsight free trial to get access to it.
I agree with James. Good point about checking Server Explorer. Right-click the database and choose Close Connection or at least check that there is a red X indicating the connection is closed. The link below is a great tutorial on the basics with Code First Migrations. The link is directly to the page within the tutorial that talks about making model changes and how to make EF happy again! http://www.asp.net/mvc/tutorials/mvc-5/introduction/adding-a-new-field. I prefer using Migrations. You would use the Package Manager Console and 1) Enable Migrations, 2) Add a migration, 3) Update the database. If in development, use LocalDb if possible, and use the Seed method in the Configuration class to prepopulate the database.

Insert data into external MSSQL database through Yii Framework

I'm using Yii Framework to create my project. I need to export some data from MySQL (my project) to an external Microsoft SQL server which is on the same network.
Basically, the user needs to click on a button (which will do the export-insert) in my view and the results should be displayed - Success (if the query has been successful) or Failure (if something went wrong).
The results part is quite easy as I'll be using 'setFlash' to display the appropriate message but I want to know how to insert data into an external database through Yii.
Do you have any idea how this can be done?
Well, I agree with #SuVeRa on the first part of defining two db instances in the config.php but i don't think the sql Commands part is necessary (Plus i hate writing sql :D )
Instead you can do:
class SomeModel extends CActiveRecord
{
...
// Override the getDbConnection() function to use the ms sql db connection
public function getDbConnection()
{
return Yii::app()->ms_sql_db_connection; // The name of the connection in config.php
}
public function transfer()
{
// Here you can do all the transferring logic using normal Yii Active Record functions
}
}
Check out the docs on getDbConnection().

Issue with getting database via Sitecore API

We noticed a slight oddity in the Sitecore API code. The code is below for your reference. The code is trying to get a database by doing new Database(database). But randomly it was failing.
This code worked for a while with Database db = new Database(database); but started failing randomly yesterday. When we changed the code to Database db = Database.GetDatabase(database);, the code started working again. What is the difference between the two approaches and what is recommended by Sitecore?
I've seen this happen twice now - multiple times in production and a couple of times in my development environment.
public static void DeleteItem(string id, stringdatabase)
{
//get the database
Database db = new Database(database);
//get the item
item = db.GetItem(new ID(id));
if (item != null)
{
using(new Sitecore.SecurityModel.SecurityDisabler())|
{
//delete the item
item.Delete();
}
}
}
A common way you will see people get a specific database is:
Sitecore.Data.Database master = Sitecore.Configuration.Factory.GetDatabase("master");
This is equivalent to Sitecore.Data.Database.GetDatabase("master").
When you call either of these methods it will first check the cache for the database. If not found it will build up the database with all of the configuration values within the config file via reflection. Once the database is created it will be placed in the cache for future use.
When you use the constructor on the database it is simply creating a rather empty database object. I am rather suprised to hear it was working at all when you used this method.
The proper approach to get a specific database would be to use:
Sitecore.Configuration.Factory.GetDatabase("master");
// or
Sitecore.Data.Database.GetDatabase("master");
If you are looking to get the database used with the current request (aka context database) you can use Sitecore.Context.Database. You can also use Sitecore.Context.ContentDatabase.

How to ensure unique column value inside code?

I am learning ASP.NET MVC, and confused as to how can I ensure unique values for columns (username & email) for a table.
Can anybody help me with a sample code or a link to the tutorial which shows & explains this?
EDIT:
I know that I can apply an unique key constraint on my table columns and achieve it. However, I want to know how can I achieve it via ASP.NET MVC code?
UPDATE:
I wish to do a check in my application such that no duplicated values are passed to DAL, i.e. achieve a check before inserting a new row.
Mliya, this is something you are controlling at the database level, not at the application level.
If you are designing a database with a users table in which you would like to constraint the username and email columns to be UNIQUE you should create a UNIQUE INDEX on such columns.
without knowing your backend database (mySQL, SQL Server, MS Access, Oracle...) it's not the case to show you pictures or tell much more, just create the table with the designer and add these unique constraints to those columns and by design you will be sure no duplicated values will ever be inserted for username and email.
I also suggest you to create an ID column which would be set as PK (primary key, which means it will be automatically set as NON NULL and UNIQUE).
From your ASP.NET MVC application you should of course make sure that no duplicated values are then passed to the DAL for username and email. You could do this in different ways, the easiest is probably to check before inserting a new row if any user already exists with that username and/or email and if so you can show a notification message telling the user to please select another pair of values.
In an ASP.NET MVC architecture, you should try to do most of your validation in the Model, but with low-level validation rules like these, it's sometimes impossible. What you should look to for answers then is Domain-driven Design (DDD) where Application Services can solve such low-level needs.
Application Services will have access to the database (either directly, or better yet; indirectly through repositories) and can perform low-level validation and throw ValidationException or something similar (with detailed information the Controller can act upon and respond to the user) when a prerequisite or business rule isn't met.
S#arp Architecture implementes all of this in a best-practice framework that you can use as a basis for your ASP.NET MVC applications. It is highly opinionated towards DDD principles and NHibernate, and it will sometimes force your hand on how you do stuff, which is kind of the point. The most important part about it is that it learns you how to deal with these kinds of problems.
To answer your question more concretely and in the spirit of DDD, this is how I would solve it:
public class UserController
{
private readonly IUserService userService;
public UserController(IUserService userService)
{
// The IUserService will be injected into the controller with
// an "Inversion of Control" container like NInject, Castle Windsor
// or StructureMap:
this.userService = userService;
}
public ActionResult Save(UserFormModel userFormModel)
{
if (userFormModel.IsValid)
{
try
{
// Mapping can be performed by AutoMapper or some similar library
UserDto userDto = Mapper.Map<UserDto>(userFormModel);
this.userService.Save(userDto);
}
catch (ValidationException ve)
{
ViewBag.Error = ve.Detail;
}
}
// Show validation errors or redirect to a "user saved" page.
}
}
public class UserService : IUserService
{
private readonly IUserRepository userRepository;
public UserService(IUserRepository userRepository)
{
// The IUserRepository will be injected into the service with
// an "Inversion of Control" container like NInject, Castle Windsor
// or StructureMap:
this.userRepository = userReposityr;
}
public UserDto Save(UserDto userDto)
{
using (this.userRepository.BeginTransaction())
{
if (!this.userRepository.IsUnique(userDto.UserName))
{
// The UserNameNotUniqueValidationException will inherit from ValidationException
// and build a Detail object that contains information that can be presented to
// a user.
throw new UserNameNotUniqueValidationException(userDto.UserName);
}
userDto = this.userRepository.Save(userDto);
this.userRepository.CommitTransaction();
return userDto;
}
}
}

Resources