public EntityApp Build(DbFirstConfig config) { _config = config; _app = new EntityApp(); var log = _app.ActivationLog; _dbSettings = new DbSettings(_config.Driver, DbOptions.Default, _config.ConnectionString); _dbSettings.SetSchemas(_config.Schemas); var modelLoader = _config.Driver.CreateDbModelLoader(_dbSettings, log); _dbModel = modelLoader.LoadModel(); Util.Check(_dbModel.Tables.Count() > 0, "No tables found in the database. Code generation aborted."); // Prepare type generator _tempNamespace = "_dummy_" + _callCount++; // artificial unique namespace for dummy interface types // Construct model setup and model GenerateModulesAndAreas(); _entityModel = new EntityModel(_app); EntityModelBuilder.SetModel(_app, _entityModel); _entityModel.ClassesAssembly = new EntityClassesAssembly(); //generate entities and members GenerateEntities(); SetupPrimaryKeys(); GenerateReferenceMembers(); CreateIndexes(); SetupKeyMembers(); return _app; }
// constructors public Database(EntityApp app, DbSettings settings) { _app = app; Settings = settings; _driver = Settings.ModelConfig.Driver; _entityModel = app.Model; _timeService = _app.TimeService; //Set list of all schemas var allSchemas = app.Areas.Select(a => settings.ModelConfig.GetSchema(a)); settings.SetSchemas(allSchemas); //Check if model is shared bool modelIsShared = Settings.ModelConfig.Options.IsSet(DbOptions.ShareDbModel); lock (_lock) { //we need lock to prevent collision on shared model if (modelIsShared) DbModel = Settings.ModelConfig.SharedDbModel; if (DbModel == null) { var dbmBuilder = new DbModelBuilder(app.Model, settings.ModelConfig, app.ActivationLog); DbModel = dbmBuilder.Build(); if (modelIsShared) Settings.ModelConfig.SharedDbModel = DbModel; } }//lock //Save }
public static DbSettings CreateDbSettings(DbServerType serverType, string connectionString = null) { var driver = CreateDriver(serverType, connectionString); var options = GetDefaultOptions(serverType); var dbStt = new DbSettings(driver, options, connectionString); return dbStt; }
public static void DropSchemaObjects(string schema) { if (Driver == null) SetupForTestExplorerMode(); //SQLite and SqlCe do not support schemas so we effectively wipe out database for each test var dbSettings = new DbSettings(Driver, DbOptions, ConnectionString); dbSettings.SetSchemas(new[] { schema }); TestUtil.DropSchemaObjects(dbSettings); }
public static DbModel LoadDbModel(string schema, MemoryLog log) { if (Driver == null) SetupForTestExplorerMode(); var dbSettings = new DbSettings(Driver, DbOptions, ConnectionString); dbSettings.SetSchemas(new[] { schema }); var loader = Driver.CreateDbModelLoader(dbSettings, log); var dbModel = loader.LoadModel(); if (log.HasErrors()) Util.Throw("Model loading errors: \r\n" + log.GetAllAsText()); return dbModel; }
public void TestMultiTenant() { // Multi-tenant test is available only for MS SQL Server. if (SetupHelper.ServerType != DbServerType.MsSql) return; const string Books2 = "VitaBooks2"; var app = SetupHelper.BooksApp; var connString2 = SetupHelper.ConnectionString.Replace("VitaBooks", Books2); var mainDbStt = SetupHelper.DbSettings; var dbSettings2 = new DbSettings(mainDbStt.ModelConfig, connString2, upgradeMode: DbUpgradeMode.Always, dataSourceName: Books2); Vita.UnitTests.Common.TestUtil.DropSchemaObjects(dbSettings2); app.ConnectTo(dbSettings2); //read from new store var ctx1 = new OperationContext(app); // DataSourceName=Default // The second context will point to another database var ctx2 = new OperationContext(app); ctx2.DataSourceName = Books2; var session = ctx2.OpenSession(); var books = session.EntitySet<IBook>().ToList(); Assert.AreEqual(0, books.Count, "Expected no books in new store"); //Let's create a pub and a book in VitaBooks2 var newPub = session.NewPublisher("VBooks"); var newBook = session.NewBook(BookEdition.Hardcover, BookCategory.Programming, "Voodoo Programming", "Voodoo science in code", newPub, DateTime.Now, 10m); session.SaveChanges(); //check we inserted them in VitaBooks2 session = ctx2.OpenSession(); var pubCopy = session.EntitySet<IPublisher>().FirstOrDefault(p => p.Name == newPub.Name); Assert.IsNotNull(pubCopy, "Publisher not found in VitaBooks2"); var bookCopy = session.EntitySet<IBook>().FirstOrDefault(b => b.Title == newBook.Title); Assert.IsNotNull(bookCopy, "Book not found."); //Check that it does not exist in 'main' VitaBooks database session = ctx1.OpenSession(); //open session in VitaBooks var pub = session.EntitySet<IPublisher>().FirstOrDefault(p => p.Name == newPub.Name); Assert.IsNull(pub, "Publisher should not exist in VitaBooks"); var book = session.EntitySet<IBook>().FirstOrDefault(b => b.Title == newBook.Title); Assert.IsNull(book, "Book should not exist in VitaBooks."); //Verify both data sources share the DbModel object var dsService = app.DataAccess; var ds1 = dsService.GetDataSource(ctx1); var ds2 = dsService.GetDataSource(ctx2); Assert.IsNotNull(ds1, "Default data source not found."); Assert.IsNotNull(ds2, "Books2 data source not found."); Assert.AreEqual(ds1.Database.DbModel, ds2.Database.DbModel, "Db models are not shared."); }
public static List<DbUpgradeScript> CompareDatabaseSchemas(DbFirstConfig config, Type modelType) { var entApp = Activator.CreateInstance(modelType) as EntityApp; entApp.Init(); // important - do not use DbOptions.AutoIndexForeignKeys - which is recommended for MS SQL, but is not helpful here. // This will create a bunch of extra indexes on FKs in entities schema and result in extra differences with original schema. // We ignore stored procs var dbOptions = DbOptions.Default & ~DbOptions.AutoIndexForeignKeys; var dbSettings = new DbSettings(config.Driver, dbOptions, config.ConnectionString, upgradeMode: DbUpgradeMode.Always, upgradeOptions : DbUpgradeOptions.UpdateTables | DbUpgradeOptions.UpdateIndexes ); dbSettings.SetSchemas(config.Schemas); var db = new Database(entApp, dbSettings); var ds = new DataSource("main", db); var upgradeMgr = new DbUpgradeManager(ds); var upgradeInfo = upgradeMgr.BuildUpgradeInfo(); return upgradeInfo.AllScripts; }
// We cannot use regular access thru EntitySession - db info/version loads at the very start of connecting to db; // the entity app is not ready yet (schema not updated, etc). public DbVersionInfo LoadDbInfo(DbSettings settings, string appName, Vita.Data.Driver.DbModelLoader loader) { var thisSchema = settings.ModelConfig.GetSchema(this.Area); if (!loader.TableExists(thisSchema, "DbInfo")) return null; var dbInfoTableName = settings.Driver.GetFullName(thisSchema, "DbInfo"); var dbModuleInfoTableName = settings.Driver.GetFullName(thisSchema, "DbModuleInfo"); try { var dbInfo = new DbVersionInfo(); var sql = string.Format("SELECT * FROM {0};", dbInfoTableName); var dt = loader.ExecuteSelect(sql); var appRow = dt.Rows.FindRow("AppName", appName); if (appRow != null) { dbInfo.InstanceType = (DbInstanceType)appRow.GetAsInt("InstanceType"); var strVersion = appRow.GetAsString("Version"); Version dbVersion; if (Version.TryParse(strVersion, out dbVersion)) dbInfo.Version = dbVersion; // 'Values' column appears in v 1.1 if (dt.Columns.Contains("Values")) { var strValues = appRow.GetAsString("Values"); DeserializeValues(dbInfo, strValues); } } //if appRow //Read modules sql = string.Format("SELECT * FROM {0};", dbModuleInfoTableName); dt = loader.ExecuteSelect(sql); foreach(DataRow row in dt.Rows) { var moduleName = row.GetAsString("ModuleName"); var schema = row.GetAsString("Schema"); var strModuleVersion = row.GetAsString("Version"); Version v; if (!Version.TryParse(strModuleVersion, out v)) v = null; dbInfo.Modules.Add(new ModuleDbVersionInfo(schema, moduleName, v)); } return dbInfo; } catch (Exception ex) { Trace.WriteLine("Failed to load DbInfo record: " + ex.ToLogString()); //Debugger.Break(); return null; } }
public void TestGetSchema() { if(SetupHelper.Driver == null) SetupHelper.SetupForTestExplorerMode(); _fileName = "_schemas_" + SetupHelper.ServerType + ".log"; System.IO.File.Delete(_fileName); WriteLine("--------------------------------------------------------------------------------------------------"); WriteLine("Server type: " + SetupHelper.ServerType + Environment.NewLine); var dbStt = new DbSettings(SetupHelper.Driver, SetupHelper.DbOptions, SetupHelper.ConnectionString); var conn = dbStt.ModelConfig.Driver.CreateConnection(SetupHelper.ConnectionString); //get col list var colList = GetCollectionNames(conn); //Report each collection foreach(var colName in colList) { WriteLine("Collection: " + colName); var dt = GetCollection(conn, colName); WriteLine("Columns: " + GetColumnNames(dt)); } }
public bool GenerateScripts(XmlDocument xmlConfig) { const string header = @"-- DDL Scripts generated by VITA DB Tool. -- Generated on: {0} -- Target database: {1} -- Executed by user {2} on machine {3}. "; _config = new DbUpdateConfig(xmlConfig); Util.Check(File.Exists(_config.AssemblyPath), "Assembly file '{0}' not found.", _config.AssemblyPath); var asm = Assembly.LoadFrom(_config.AssemblyPath); var appType = asm.GetType(_config.AppClassName); Util.Check(appType != null, "Type {0} not found in target assembly."); // Using NonPublic flag to allow internal constructor; // EntityApp must have a parameterless constructor, but it may be made internal, to hide from regular code var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; var appObj = Activator.CreateInstance(appType, flags, null, null, null); Util.Check(appObj != null, "Failed to create instance of class {0}.", _config.AppClassName); var entApp = appObj as EntityApp; Util.Check(entApp != null, "The target instance of class {0} is not an EntityApp instance.", _config.AppClassName); entApp.Init(); var dbSettings = new DbSettings(_config.Driver, _config.DbOptions, _config.ConnectionString, upgradeMode: DbUpgradeMode.Always, upgradeOptions: _config.ModelUpdateOptions); var schemas = entApp.Areas.Select(a => a.Name).ToList(); dbSettings.SetSchemas(schemas); var db = new Database(entApp, dbSettings); var ds = new DataSource(null, db); var updateMgr = new DbUpgradeManager(ds); var upgrades = updateMgr.BuildUpgradeInfo(); var ddl = string.Join(_config.Driver.DDLSeparator, upgrades.AllScripts.Select(scr => scr.Sql)); if (string.IsNullOrEmpty(ddl)) ddl = "-- (No changes detected)"; var text = string.Format(header, DateTime.Now.ToString("s"), _config.ConnectionString, Environment.UserName, Environment.MachineName) + ddl; File.WriteAllText(_config.OutputPath, text); _feedback.WriteLine(" Generated {0} scripts.", upgrades.AllScripts.Count); _feedback.WriteLine(" DDL scripts are saved to '{0}'", _config.OutputPath); return true; }
public static EntityApp ActivateApp(EntityApp app, bool updateSchema = true, bool dropUnknownTables = false) { DeleteLocalLogFile(); app.LogPath = LogFilePath; //If driver is not set, it means we are running from Test Explorer in VS. Use ServerTypeForTestExplorer if(Driver == null) SetupForTestExplorerMode(); try { app.Init(); var upgradeMode = updateSchema ? DbUpgradeMode.Always : DbUpgradeMode.Never; var upgradeOptions = DbUpgradeOptions.Default; if(dropUnknownTables) upgradeOptions |= DbUpgradeOptions.DropUnknownObjects; var dbSettings = new DbSettings(Driver, DbOptions, ConnectionString, upgradeMode: upgradeMode, upgradeOptions: upgradeOptions); app.ConnectTo(dbSettings); return app; } catch (StartupFailureException sx) { //Unit test framework shows only ex message, not details; let's write specifics into debug output - it will be shown in test failure report Debug.WriteLine("EntityApp init exception: "); Debug.WriteLine(sx.Log); throw; } }
public static BooksEntityApp CreateConfigureBooksApp() { // set up application var protectedSection = (NameValueCollection)ConfigurationManager.GetSection("protected"); var cryptoKey = protectedSection["LoginInfoCryptoKey"]; var booksApp = new BooksEntityApp(cryptoKey); booksApp.Init(); var connString = protectedSection["MsSqlConnectionString"]; var logConnString = protectedSection["MsSqlLogConnectionString"]; var driver = MsSqlDbDriver.Create(connString); var dbOptions = MsSqlDbDriver.DefaultMsSqlDbOptions; var logDbSettings = new DbSettings(driver, dbOptions, logConnString); booksApp.LoggingApp.ConnectTo(logDbSettings); var dbSettings = new DbSettings(driver, dbOptions, connString, upgradeMode: DbUpgradeMode.Always); booksApp.ConnectTo(dbSettings); //Web Api WebHelper.ConfigureWebApi(GlobalConfiguration.Configuration, booksApp, logLevel: Entities.Services.LogLevel.Details); /* var hc = GlobalConfiguration.Configuration; var webH = hc.MessageHandlers.First(h => h is WebCallContextHandler); hc.MessageHandlers.Remove(webH); */ return booksApp; }
public override DbModelUpdater CreateDbModelUpdater(DbSettings settings) { return new MySqlDbModelUpdater(settings); }
public override DbModelLoader CreateDbModelLoader(DbSettings settings, MemoryLog log) { return new MySqlDbModelLoader(settings, log); }
public static void InitImpl() { if(BooksApp != null) return; LogFilePath = ConfigurationManager.AppSettings["LogFilePath"]; DeleteLocalLogFile(); var protectedSection = (NameValueCollection)ConfigurationManager.GetSection("protected"); var loginCryptoKey = protectedSection["LoginInfoCryptoKey"]; var connString = protectedSection["MsSqlConnectionString"]; var logConnString = protectedSection["MsSqlLogConnectionString"]; BooksApp = new BooksEntityApp(loginCryptoKey); //Add mock email/sms service NotificationListener = new NotificationListener(BooksApp, blockAll: true); //Set magic captcha in login settings, so we can pass captcha in unit tests var loginStt = BooksApp.GetConfig<Vita.Modules.Login.LoginModuleSettings>(); loginStt.MagicCaptcha = "Magic"; BooksApp.Init(); //connect to database var driver = MsSqlDbDriver.Create(connString); var dbOptions = MsSqlDbDriver.DefaultMsSqlDbOptions; var dbSettings = new DbSettings(driver, dbOptions, connString, upgradeMode: DbUpgradeMode.Always); // schemas); var resetDb = ConfigurationManager.AppSettings["ResetDatabase"] == "true"; if(resetDb) Vita.UnitTests.Common.TestUtil.DropSchemaObjects(dbSettings); BooksApp.ConnectTo(dbSettings); var logDbSettings = new DbSettings(driver, dbOptions, logConnString); BooksApp.LoggingApp.ConnectTo(logDbSettings); BooksApp.LoggingApp.LogPath = LogFilePath; TestUtil.DeleteAllData(BooksApp, exceptEntities: new [] {typeof(IDbInfo), typeof(IDbModuleInfo)}); TestUtil.DeleteAllData(BooksApp.LoggingApp); SampleDataGenerator.CreateUnitTestData(BooksApp); var serviceUrl = ConfigurationManager.AppSettings["ServiceUrl"]; StartService(serviceUrl); Client = new WebApiClient(serviceUrl); Client.InnerHandler.AllowAutoRedirect = false; //we need it for Redirect test }
public static void InitApp() { Util.Check(!_initFailed, "App initialization failed. Cannot run tests. See other tests output for failure details."); if(BooksApp != null) return; try { //force randomization of schema update SQLs, to test that they will put in correct order anyway DbModelUpdater.Test_RandomizeInitialSchemaUpdatesOrder = true; //Check if Reset was called; if Driver is null, we are running in Test Explorer mode if(Driver == null) SetupForTestExplorerMode(); //Reset Db and drop schema objects var resetDb = ConfigurationManager.AppSettings["ResetDatabase"] == "true"; if(resetDb) Vita.UnitTests.Common.TestUtil.DropSchemaObjects(DbSettings); //Setup model, initialize Books module, create database model, update schema ------------------------------------------------- BooksApp = new BooksEntityApp(LoginCryptoKey); BooksApp.LogPath = LogFilePath; BooksApp.ActivationLogPath = ActivationLogFilePath; BooksApp.CacheSettings.CacheEnabled = CacheEnabled; NotificationListener = new NotificationListener(BooksApp, blockAll: true); //SmtpMock for testing password reset and other processes BooksApp.Init(); //Now connect the main app BooksApp.ConnectTo(DbSettings); //if we have logging app as a separate app - we need to connect it too. // NOTE: good pracice to connect LoggingApp before we connect the main app, so it can log main database update scripts // but it should work anyway. var logDbSettings = new DbSettings(Driver, DbSettings.ModelConfig.Options, LogConnectionString); BooksApp.LoggingApp.ConnectTo(logDbSettings); Thread.Yield(); CreateSampleData(); } catch(ClientFaultException cfx) { Debug.WriteLine("Validation errors: \r\n" + cfx.ToString()); throw; } catch(Exception sx) { _initFailed = true; //Unit test framework shows only ex message, not details; let's write specifics into debug output - it will be shown in test failure report Debug.WriteLine("app init encountered errors: "); Debug.WriteLine(sx.ToLogString()); throw; } }
//Prepares for full run with a specified server internal static void Reset(TestConfig config) { if(BooksApp != null) BooksApp.Flush(); Thread.Sleep(100); //to allow log dump of buffered messages DeleteLogFiles(); //it will happen only once WriteLog("\r\n------------------------ " + config.ToString() + "---------------------------------------------\r\n\r\n"); ServerType = config.ServerType; CacheEnabled = config.EnableCache; UseBatchMode = config.UseBatchMode; BooksApp = null; _initFailed = false; var protectedSection = (NameValueCollection)ConfigurationManager.GetSection("protected"); //Load connection string ConnectionString = ReplaceBinFolderToken(protectedSection[ServerType + "ConnectionString"]); Util.Check(!string.IsNullOrEmpty(ConnectionString), "Connection string not found for server: {0}.", ServerType); LogConnectionString = ReplaceBinFolderToken(protectedSection[ServerType + "LogConnectionString"]); LogConnectionString = LogConnectionString ?? ConnectionString; LoginCryptoKey = protectedSection["LoginInfoCryptoKey"]; Driver = ToolHelper.CreateDriver(ServerType, ConnectionString); var dbOptions = ToolHelper.GetDefaultOptions(ServerType); if (config.UseStoredProcs) dbOptions |= DbOptions.UseStoredProcs; else dbOptions &= ~DbOptions.UseStoredProcs; if (config.UseBatchMode) dbOptions |= DbOptions.UseBatchMode; else dbOptions &= ~DbOptions.UseBatchMode; // dbOptions |= DbOptions.ForceArraysAsLiterals; -- just to test this flag DbSettings = new DbSettings(Driver, dbOptions, ConnectionString, upgradeMode: DbUpgradeMode.Always); //Test: remap login schema into login2 DbSettings.ModelConfig.MapSchema("login", "login2"); }
private bool InitApp() { Application.ThreadException += Application_ThreadException; try { var serviceURl = ConfigurationManager.AppSettings.Get("serviceUrl"); _app = new OAuthEntityApp(serviceURl); _app.Init(); // Get IOAuthClientService and hook to it's Redirected event - to get notified when user hits "Allow" _service = _app.GetService<IOAuthClientService>(); _service.Redirected += OAuthClientService_Redirected; //Setup default encryption channel - we store OAuth data encrypted var cryptoKey = ConfigurationManager.AppSettings.Get("CryptoKey"); var encrService = _app.GetService<Vita.Modules.EncryptedData.IEncryptionService>(); encrService.AddChannel(HexUtil.HexToByteArray(cryptoKey)); //Connect to db var connString = ConfigurationManager.AppSettings.Get("MsSqlConnectionString"); if(!CheckConnection(connString)) return false; var dbSettings = new DbSettings(new MsSqlDbDriver(), MsSqlDbDriver.DefaultMsSqlDbOptions, connString); _app.ConnectTo(dbSettings); //Start local web server to handle redirects back from OAuth server, after user approves access StartWebService(serviceURl); // Hook to global error log, to show exception when it happens in Redirect controller var errLog = _app.GetService<IErrorLogService>(); errLog.ErrorLogged += ErrLog_ErrorLogged; //Just for ease of debugging this app, update servers definitions in database var session = OpenSession(); Vita.Modules.OAuthClient.OAuthServers.CreateUpdatePopularServers(session); session.SaveChanges(); return true; } catch(Exception ex) { Log(ex.ToLogString()); MessageBox.Show(ex.Message, "Error"); return false; } }
public SQLiteDbModelLoader(DbSettings settings, MemoryLog log) : base(settings, log) { }