Author |
Share Topic Topic Search Topic Options
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Topic: Manual Custom Connection without having to leave the application Posted: 22-Sep-2012 at 1:59am |
Sorry it took me a while to look into this. The issue here is that the States entities are cached by the StaffingResourceAddressListViewModel between sessions. You have to clear them when the VM closes, so they get loaded fresh from the correct data source, otherwise they don't match. Modify StaffingResourceAddressListViewModel.OnDeactivate as follows: protected override void OnDeactivate(bool close)
{
base.OnDeactivate(close);
if (!close) return;
ClearAddresses();
States = null;
}
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 12-Sep-2012 at 10:13am |
Sorry, I have not. I should have time next week.
|
|
giotis
Groupie
Joined: 26-Apr-2012
Location: Greece
Posts: 53
|
Post Options
Quote Reply
Posted: 12-Sep-2012 at 9:41am |
hello Marcel you found time for analysis
|
|
giotis
Groupie
Joined: 26-Apr-2012
Location: Greece
Posts: 53
|
Post Options
Quote Reply
Posted: 06-Sep-2012 at 7:42am |
test by your self (Cocktail ver 19545) I'll only take 2 minutes
namespace Common { public interface IUserSession { string Name { get; set; } } } namespace Common{ [Export(typeof(IUserSession)), PartCreationPolicy(CreationPolicy.Shared)] public class UserSession : IUserSession { private string _name; public UserSession() { } public string Name { get { return _name; } set { _name = value; } } } } namespace TempHire { public class CustomDataSourceKeyResolver : IDataSourceKeyResolver { public IdeaBlade.EntityModel.IDataSourceKey GetKey(string keyName, string keyExtension, bool onServer) { if (!onServer) { return null; } if (string.IsNullOrEmpty(keyExtension)) { return null; } if (keyName != "TempHireEntities") { return null; } String connectionString = ""; if (keyExtension == "PROD") { connectionString = @"Data Source=|DataDirectory|TempHire_Prod.sdf"; } if (keyExtension == "TEST") { connectionString = @"Data Source=|DataDirectory|TempHire_Test.sdf"; } string name = string.IsNullOrEmpty(keyExtension) ? keyName : keyName + "_" + keyExtension; return new ClientEdmKey(name, connectionString, false, "FromResolver"); } } } namespace TempHire { public class EnvironmentResolver : IConnectionOptionsResolver { private static ConnectionOptions TestEnv = ConnectionOptions.Default.WithDataSourceExtension("TEST"); private static ConnectionOptions ProdEnv = ConnectionOptions.Default.WithDataSourceExtension("PROD"); private IUserSession _userSession; [ImportingConstructor] public EnvironmentResolver(IUserSession userSession) { _userSession = userSession; } public ConnectionOptions GetConnectionOptions(string name) { if (name == ConnectionOptions.Default.Name) { switch (_userSession.Name) { case "Test": return TestEnv.WithName(ConnectionOptions.Default.Name); case "Prod": return ProdEnv.WithName(ConnectionOptions.Default.Name);
default: return null; } //return ConnectionOptions.Default.WithDataSourceExtension(_userSession.Name.ToUpper()).WithName(ConnectionOptions.Default.Name); } return null; } } }
namespace TempHire.ViewModels.Login { using System.Linq;
[Export] public class LoginViewModel : Screen, IResult { ....... private IUserSession _userSession; private string _displayMemberPath; private BindableCollection<object> _items; private object _selectedItem;
[ImportingConstructor] public LoginViewModel(IAuthenticationService authenticationService, IWindowManager windowManager, [Import(AllowDefault = true)] IGlobalCache globalCache, IUserSession userSession) { _userSession = userSession; DisplayMemberPath = "WithName"; Items = new BindableCollection<object>() { new Connections() { WithName = "Test" }, new Connections() { WithName = "Prod" } }; } private class Connections { public Connections() { } public string WithName { get; set; } } public string DisplayMemberPath { get { return _displayMemberPath; } set { _displayMemberPath = value; NotifyOfPropertyChange(() => DisplayMemberPath); } } public object SelectedItem { get { return _selectedItem; } set { _selectedItem = value; NotifyOfPropertyChange(() => SelectedItem); _userSession.Name = ((Connections)SelectedItem).WithName; } } public BindableCollection<object> Items { get { return _items; } set { _items = value; NotifyOfPropertyChange(() => Items); SelectedItem = _items.FirstOrDefault(); } }
LoginView after password <ComboBox x:Name="Items" Grid.Row="3" Grid.Column="1" Height="25" Margin="2,2,81,2" VerticalAlignment="Center" DisplayMemberPath="{Binding DisplayMemberPath}" Width="137" />
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 05-Sep-2012 at 10:14am |
Not sure without debugging the code. Are you logging out before switching the database?
|
|
giotis
Groupie
Joined: 26-Apr-2012
Location: Greece
Posts: 53
|
Post Options
Quote Reply
Posted: 04-Sep-2012 at 11:45pm |
I put a TextBlock in StaffingResourceAddressListView <TextBlock Text="{Binding Item.StateId}" />
everything work fine ComboBox have problem
<ComboBox Grid.Row="4" Grid.Column="1" Width="140" Height="25" Margin="2" HorizontalAlignment="Left" DisplayMemberPath="Name" ItemsSource="{Binding ElementName=LayoutRoot, Path=DataContext.States}" MaxDropDownHeight="200" SelectedValue="{Binding Item.StateId, ValidatesOnDataErrors=True, ValidatesOnExceptions=True, Mode=TwoWay}" SelectedValuePath="Id" />
|
|
giotis
Groupie
Joined: 26-Apr-2012
Location: Greece
Posts: 53
|
Post Options
Quote Reply
Posted: 04-Sep-2012 at 11:11pm |
Sorry filled, the combobox not show the state from Adresses
|
|
giotis
Groupie
Joined: 26-Apr-2012
Location: Greece
Posts: 53
|
Post Options
Quote Reply
Posted: 04-Sep-2012 at 11:07pm |
After selecting base (Prod) and connect all is well When after changing the base(Test) the combobox(State) from Adresses are not filled, If we go back to first base again all well
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 04-Sep-2012 at 10:56pm |
I'm not following your question. Please elaborate.
|
|
giotis
Groupie
Joined: 26-Apr-2012
Location: Greece
Posts: 53
|
Post Options
Quote Reply
Posted: 04-Sep-2012 at 10:53pm |
thank you very much Also when we change the connection not fill the comboboxes at second database, when change again the first database the comboboxes is correct why?
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 04-Sep-2012 at 10:37pm |
Well, Default is used if the EntityManagerProvider and AuthenticationSerivce are not configured with another ConnectionOptions. You should always check what name needs to be resolved. You may decide later on to use different ConnectionOptions names. If you can't resolve the name than you return null in which case Cocktail looks for another resolver that might now how to resolve the name. There's a default resolver that knows how to resolve Default, Fake and DesignTime if all fails.
|
|
giotis
Groupie
Joined: 26-Apr-2012
Location: Greece
Posts: 53
|
Post Options
Quote Reply
Posted: 04-Sep-2012 at 10:28pm |
perfect I noticed when GetConnectionOptions take value is always "Default" and ConnectionOptions.Default.Name having the same value , always , that is correct? because in this case we do not need to check out.
Also when we change the connection not fill the comboboxes at second database, when change again the first database the comboboxes is correct
Edited by giotis - 04-Sep-2012 at 10:46pm
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 04-Sep-2012 at 12:17am |
Sorry, I was swamped. What exactly are you stuck on? You can make this a lot simpler by writing a ConnectionOptionsResolver that simply replaces the system default ConnectionOptions based on the user's selection.
public class EnvironmentResolver : IConnectionOptionsResolver { private static ConnectionOptions DevEnv = ConnectionOptions.Default.WithDataSourceExtension("DEV");
private static ConnectionOptions TestEnv = ConnectionOptions.Default.WithDataSourceExtensioin("TEST");
private static ConnectionOptions ProdEnv = ConnectionOptions.Default.WithDataSourceExtension("PROD");
private IUserSession _userSession;
[ImportingConstructor] public EnvironmentResolver(IUserSession userSession) { _userSession = userSession; }
public ConnectionOptions GetConnectionOptions(string name) { if (name == ConnectionOptions.Default.Name) { switch (_userSession.Name) { "DEV" : return DevEnv.WithName(ConnectionOptions.Default.Name); "TEST" : return TestEnv.WithName(ConnectionOptions.Default.Name); "PROD" : return ProdEnv.WithName(ConnectionOptions.Default.Name);
default : return null; } }
return null; } }
Now you don't have to worry about configuring the EntityManagerProvider or the AuthenticationService. They'll keep looking for the default ConnectionOptions and the above resolver simply feeds a properly configured ConnectionOptions instead of the system default.
|
|
giotis
Groupie
Joined: 26-Apr-2012
Location: Greece
Posts: 53
|
Post Options
Quote Reply
Posted: 28-Aug-2012 at 4:21pm |
Dear Marcel so far no so good,
my steps
a. public interface IUserSession { string Name { get; set; } }
[Export(typeof(IUserSession)), PartCreationPolicy(CreationPolicy.Shared)] public class UserSession : IUserSession { public UserSession() { } public string Name { get; set; } }
b.public class EnvironmentResolver : IConnectionOptionsResolver { public ConnectionOptions GetConnectionOptions(string name) { IUserSession userSession = Composition.GetInstance<IUserSession>(CreationPolicy.Shared); if (name == userSession.Name) return ConnectionOptions.Default.WithDataSourceExtension( userSession.Name.ToUpper()).WithName(userSession.Name); return null; } } c. <connectionStrings> <add name="SecurityEntities" connectionString=... </connectionStrings>
d.class CustomDataSourceKeyResolver : IDataSourceKeyResolver { public GetKey(string keyName, string keyExtension, bool onServer) { if (!onServer) {return null;} if (keyName != "TempHireEntities" || string.IsNullOrEmpty(keyExtension)) { return null; } String connectionString = ""; if (keyExtension == "PROD") { connectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=TempHire_Production; ... } if (keyExtension == "TEST") { connectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=TempHire_Test; ... }
if(string.IsNullOrEmpty(connectionString ) { return null; }
// Now build and return a "ClientEdmKey". string name = string.IsNullOrEmpty(keyExtension) ? keyName : keyName + "_" + keyExtension; return new ClientEdmKey(name, connectionString, false, "FromResolver"); } }
e.[Export] public IEntityManagerProvider<TempHireEntities> TempHireEntityManagerProvider { get { IUserSession userSession = Composition.GetInstance<IUserSession>(CreationPolicy.Shared); var provider = new EntityManagerProvider<TempHireEntities>() .Configure(config => config.WithConnectionOptions(userSession.Name)); return provider; } }
f. [ImportingConstructor] public LoginViewModel(IAuthenticationService authenticationService, IWindowManager windowManager, [Import(AllowDefault = true)] IPreLoader preLoader, IUserSession userSession .... _userSession = userSession; ....
_userSession.Name = filled from one new field named KeyName public string KeyName { get { return _keyName; } set { _keyName= value; _userSession.Name = value; NotifyOfPropertyChange(() => KeyName); NotifyOfPropertyChange(() => CanLogin); } }
g. before Login public IEnumerable<IResult> Login() {
_authenticationService. ??? There is no implementation to configure ConnectionOptions using (Busy.GetTicket()) ...
I am stuck
ps. If CustomDataSourceKeyResolver return null how can it manage from LoginViewModel
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 22-Jul-2012 at 7:39pm |
I'm not sure I follow. IDataSourceKeyResolver.GetKey gets called for each unique keyName/keyExtension pair. So, if we go back to my earlier example. The first time you connect to DEV it gets called with keyName="TempHireEntities" and keyExtension="DEV". The first time you connect to TEST it gets called with keyName="TempHireEntities" and keyExtension="TEST" and so on. In each case you return the appropriate connection string to the corresponding physical DB.
|
|
giotis
Groupie
Joined: 26-Apr-2012
Location: Greece
Posts: 53
|
Post Options
Quote Reply
Posted: 22-Jul-2012 at 4:13pm |
DataSourceKeyResolver run only once, how do I switch?
|
|