I am trying to make a Standalone Application using SQLite in Unity3D,
I am getting a strange problem.
I created a database using sqliteadmin, and created a Table named Admin, having field: id, email, password.
I am able to Login using email and password but in Unity Edit Mode.
Its working fine but when i build it and then run it, its not working, I have no idea why?
Reference
Here is my code:
using UnityEngine;
using System.Collections;
using Mono.Data.Sqlite;
using System.Data;
using System;
using UnityEngine.UI;
public class DatabaseConnection : MonoBehaviour {
public Text em;
public Text pas;
public static int id;
public static string email ="";
public static string password="";
public static string wrong="Wrong Email/Password !!!";
public Text Wrong;
public GameObject loading;
private ButtonsController bc;
public GameObject loginPanel;
void Start () {
string conn = "URI=file:" + Application.dataPath + "/Database/TMDB.s3db";
IDbConnection dbconn;
dbconn = (IDbConnection)new SqliteConnection (conn);
dbconn.Open ();
IDbCommand dbcmd = dbconn.CreateCommand ();
string sqlQuery = "SELECT id, email, password " + "FROM Admin";
dbcmd.CommandText = sqlQuery;
IDataReader reader = dbcmd.ExecuteReader ();
while (reader.Read()) {
id = reader.GetInt32 (0);
email = reader.GetString(1);
password = reader.GetString(2);
}
reader.Close ();
reader = null;
dbcmd.Dispose ();
dbcmd = null;
dbconn.Close ();
dbconn = null;
loading.SetActive (false);
}
public void login()
{
if ((em.text == email) && (pas.text == password)) {
Debug.Log ("Success");
loading.SetActive (true);
loginPanel.SetActive(false);
Application.LoadLevel(1);
} else {
Debug.Log ("Error");
Wrong.text = wrong.ToString ();
}
}
}
Application.datapath is readonly.
What you need is Application.persistentDataPath
Checkout this link
http://answers.unity3d.com/questions/209108/when-to-use-persistentdatapath-versus-datapath.html
Create StreamingAssets folder into your Assets, and use this connection string:
string conn = "URI=file:" +
System.IO.Path.Combine(Application.streamingAssetsPath, "Database/TMDB.s3db");
Using streaming asset is necessary, it places files into the normal filesystem on the target machine to make them accessible via a pathname.
More info:
https://docs.unity3d.com/Manual/StreamingAssets.html
dude ,,, just check the files bro,,, after building the database is empty so go and replace the database file with the one u been working on with the same database name .
Related
I have just started to use FluentMigration for my current project. I wrote my first migration but I have some trouble writing a unit test for it.
Here is some sample code:
private ServiceProvider CreateServiceProvider()
{
return new ServiceCollection()
.AddLogging(lb => lb.AddFluentMigratorConsole())
.AddFluentMigratorCore()
.ConfigureRunner(
builder => builder
.AddSQLite()
.WithGlobalConnectionString("Data Source=:memory:;Version=3;New=True;")
.WithMigrationsIn(typeof(MigrationOne).Assembly))
.BuildServiceProvider();
}
private void PerformMigrateUp(IServiceScope scope)
{
var runner = scope.ServiceProvider.GetRequiredService<IMigrationRunner>();
runner.MigrateUp(1);
}
[Test]
public void ShouldHaveTablesAfterMigrateUp()
{
var provider = this.CreateServiceProvider();
using (var scope = provider.CreateScope())
{
this.PerformMigrateUp(scope);
// here I'd like to test if tables have been created in the database by the migration
}
}
I don't know how (or if it is possible) to access the current database connection so I can perform a query. Any suggestions would be helpful. Thanks.
Ok, I found a solution. I have to use the Process method of the runner's processor to perform my own sql query.
It looks like this:
private ServiceProvider CreateServiceProvider()
{
return new ServiceCollection()
.AddLogging(lb => lb.AddFluentMigratorConsole())
.AddFluentMigratorCore()
.ConfigureRunner(
builder => builder
.AddSQLite()
.WithGlobalConnectionString(#"Data Source=:memory:;Version=3;New=True;")
.WithMigrationsIn(typeof(MigrationDate20181026113000Zero).Assembly))
.BuildServiceProvider();
}
[Test]
public void ShouldHaveNewVersionAfterMigrateUp()
{
var serviceProvider = this.CreateServiceProvider();
var scope = serviceProvider.CreateScope();
var runner = scope.ServiceProvider.GetRequiredService<IMigrationRunner>();
runner.MigrateUp(1);
string sqlStatement = "SELECT Description FROM VersionInfo";
DataSet dataSet = runner.Processor.Read(sqlStatement, string.Empty);
Assert.That(dataSet, Is.Not.Null);
Assert.That(dataSet.Tables[0].Rows[0].ItemArray[0], Is.EqualTo("Migration1"));
}
This is an old question but an important one. I find it strange that I couldnt find any documentation on this.
In any case here is my solution which I find to be a bit better as you dont need to rely on the runner. Since you dont need that the options open up hugely for constructor arguments.
Firstly make sure you install Microsoft.Data.Sqlite or you will get a strange error.
SQLite in memory databases exist for as long as the connection does - and 1 database per connection on first glance. Actually though there is a way to share the database between connections as long as at least 1 connection is open at all times according to my experiments. You just need to name it.
https://learn.microsoft.com/en-us/dotnet/standard/data/sqlite/connection-strings#sharable-in-memory
So to begin with I created a connection that will stay open until the test finishes. It will be named using Guid.NewGuid() so that subsequent connections will work as expected.
var dbName = Guid.NewGuid().ToString();
var connectionString = $"Data Source={dbName};Mode=Memory;Cache=Shared";
var connection = new SqliteConnection(connectionString);
connection.Open();
After that the crux of running the migrations is the same as previously answered but the connection string uses the named database:
var sp = services.AddFluentMigratorCore()
.ConfigureRunner(fluentMigratorBuilder => fluentMigratorBuilder
.AddSQLite()
.WithGlobalConnectionString(connectionString)
.ScanIn(AssemblyWithMigrations).For.Migrations()
)
.BuildServiceProvider();
var runner = sp.GetRequiredService<IMigrationRunner>();
runner.MigrateUp();
Here is a class I use to inject a connection factory everywhere that needs to connect to the database for normal execution:
internal class PostgresConnectionFactory : IConnectionFactory
{
private readonly string connectionString;
public PostgresConnectionFactory(string connectionString)
{
this.connectionString = connectionString;
}
public DbConnection Create()
{
return new NpgsqlConnection(connectionString);
}
}
I just replaced this (all hail dependency inversion) with:
internal class InMemoryConnectionFactory : IConnectionFactory
{
private readonly string connectionstring;
public InMemoryConnectionFactory(string connectionstring)
{
this.connectionstring = connectionstring;
}
public DbConnection Create()
{
return new SqliteConnection(connectionstring);
}
}
where the connection string is the same named one I defined above.
Now you can simply use that connection factory anywhere that needs to connect to the same in memory database, and since we can now connect multiple times possibilities for integration testing open up.
Here is the majority of my implementation:
public static IDisposable CreateInMemoryDatabase(Assembly AssemblyWithMigrations, IServiceCollection services = null)
{
if (services == null)
services = new ServiceCollection();
var connectionString = GetSharedConnectionString();
var connection = GetPersistantConnection(connectionString);
MigrateDb(services, connectionString, AssemblyWithMigrations);
services.AddSingleton<IConnectionFactory>(new InMemoryConnectionFactory(connectionString));
return services.BuildServiceProvider()
.GetRequiredService<IDisposableUnderlyingQueryingTool>();
}
private static string GetSharedConnectionString()
{
var dbName = Guid.NewGuid().ToString();
return $"Data Source={dbName};Mode=Memory;Cache=Shared";
}
private static void MigrateDb(IServiceCollection services, string connectionString, Assembly assemblyWithMigrations)
{
var sp = services.AddFluentMigratorCore()
.ConfigureRunner(fluentMigratorBuilder => fluentMigratorBuilder
.AddSQLite()
.WithGlobalConnectionString(connectionString)
.ScanIn(assemblyWithMigrations).For.Migrations()
)
.BuildServiceProvider();
var runner = sp.GetRequiredService<IMigrationRunner>();
runner.MigrateUp();
}
private static IDbConnection GetPersistantConnection(string connectionString)
{
var connection = new SqliteConnection(connectionString);
connection.Open();
return connection;
}
Then here is a sample test:
public Test : IDisposable {
private readonly IDisposable _holdingConnection;
public Test() {
_holdingConnection = CreateInMemoryDatabase(typeof(MyFirstMigration).Assembly);
}
public void Dispose() {
_holdingConnection.Dispose();
}
}
You may notice that the static factory returns a custom interface. Its just an interface that extends the normal tooling I inject to repositories, but also implements IDisposable.
Untested bonus for integration testing where you will have a service collection created via WebApplicationFactory or TestServer etc:
public void AddInMemoryPostgres(Assembly AssemblyWithMigrations)
{
var lifetime = services.BuildServiceProvider().GetService<IHostApplicationLifetime>();
var holdingConnection= InMemoryDatabaseFactory.CreateInMemoryDapperTools(AssemblyWithMigrations, services);
lifetime.ApplicationStopping.Register(() => {
holdingConnection.Dispose();
});
}
I'm executing queries periodically (by a scheduler) using my Spring Boot application
application.properties
src_mssqlserver_url=jdbc:sqlserver://192.168.0.1;databaseName=Test;
src_mssqlserver_username=tester
src_mssqlserver_password=tester1
src_mssqlserver_driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
Datasource and JdbcTemplate Bean
#Primary
#Bean(name = "src_mssqlserver")
#ConfigurationProperties(prefix = "spring.ds_mssqlserver")
public DataSource srcDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("src_mssqlserver_driverClassName"));
dataSource.setUrl(env.getProperty("src_mssqlserver_url"));
dataSource.setUsername(env.getProperty("src_mssqlserver_username"));
dataSource.setPassword(env.getProperty("src_mssqlserver_password"));
return dataSource;
}
#Bean(name = "srcJdbcTemplate")
public JdbcTemplate srcJdbcTemplate(#Qualifier("src_mssqlserver") DataSource dsSrcSqlServer) {
return new JdbcTemplate(dsSrcSqlServer);
}
Usage: This method is called from a scheduler with list of items to process (normally 1000 records), this process runs in an hour once.
#Autowired
#Qualifier("srcJdbcTemplate")
private JdbcTemplate srcJdbcTemplate;
public void batchInsertUsers(final List<User> users) {
String queryInsert = "INSERT INTO [User] ([Name]"
+ " , [Created_Date]"
+ " , [Notes])"
+ " VALUES (?, SYSDATETIMEOFFSET(), ?)";
srcJdbcTemplate.batchUpdate(queryInsert, new BatchPreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
User user = users.get(i);
ps.setString(1, user.getName());
ps.setString(2, user.getNotes());
}
#Override
public int getBatchSize() {
return sites.size();
}
});
I'm getting warnings from database administrator that my code keeping too much connections open. Please share some standard and workable way to handle such situation.
Thanks.
DriverManagerDataSource is NOT meant for production, it opens and closes a connection each time it needs one.
Use a connection pool like c3p0DataSource.
being an Android Studio beginner i tend to get lots and lots of tiny errors i cannot find out, please let me know what I am doing wrong because I've tried all the other answers somehow and it doesn't get better :)
public class DatabaseHelper extends SQLiteOpenHelper{
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "UserManager.db";
private static final String TABLE_USER = "user";
private static final String COLUMN_USER_ID= "user_id";
private static final String COLUMN_USER_NAME= "user_name";
private static final String COLUMN_USER_EMAIL= "user_email";
private static final String COLUMN_USER_PASSWORD= "user_password";
private String CREATE_USER_TABLE = "CREATE TABLE " + TABLE_USER + "(" +
COLUMN_USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ COLUMN_USER_NAME + " TEXT," + COLUMN_USER_EMAIL + " TEXT," +
COLUMN_USER_PASSWORD + " TEXT" + ")";
private String DROP_USER_TABLE = " DROP TABLE IF EXISTS " + TABLE_USER;
public DatabaseHelper(Context context){
super(context, DATABASE_NAME,null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db){
db.execSQL(CREATE_USER_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
db.execSQL(DROP_USER_TABLE);
onCreate(db);
}
public void addUser(User user){
SQLiteDatabase db= this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_USER_NAME, user.getName());
values.put(COLUMN_USER_EMAIL, user.getEmail());
values.put(COLUMN_USER_PASSWORD, user.getPassword());
db.insert(TABLE_USER,null, values);
db.close();
}
public boolean checkUser(String password, String email){
String[] columns = {
COLUMN_USER_ID
};
SQLiteDatabase db= this.getWritableDatabase();
String selection = COLUMN_USER_EMAIL + " = ? " + "AND "+ COLUMN_USER_PASSWORD+" =? ";
String[] selectionArgs = { email,password };
Cursor cursor = db.query(TABLE_USER,
columns,
selection,
selectionArgs,
null,
null,
null);
int cursorCount = cursor.getCount();
cursor.close();
db.close();
if(cursorCount > 0){
return true;
}
return false;
}
}
I know the logcat let me know this:
07-11 22:08:29.072 9071-9071/com.example.lavinia.sqllogin E/AndroidRuntime:
FATAL EXCEPTION: main
Process: com.example.lavinia.sqllogin, PID: 9071
android.database.sqlite.SQLiteException: no such column: user_id (code 1
SQLITE_ERROR): , while compiling: SELECT user_id FROM user WHERE user_email =
?AND user_password =?
And I can't find the wrong usage of user_id, I think I used it fine and the app will stop working after I Login myself. (the app has login and registration activities- and the registration works ok, but pressing the Login button in the Login.activity will make the app crash)
Thank you very much for you support :) If needed, I will provide with further code.
This issue is probably due to i tend to get lots and lots of tiny errors in conjunction with a common misconception regarding the onCreate method.
The onCreate method automatically runs only once when the database is and has actually been created. It does not run every time the App is run.
As such any changes (corrections included) to the structure (tables and columns) will not be applied if they are coded/actioned within the onCreate method.
When developing the easiest fix is to do one of the following 3:-
delete the App's data (deletes the database so onCreate will be called).
uninstall the App (deletes the database so onCreate will be called).
if the onUpgrade method will drop the table(s) and then call onCreate , to increase the database version number as passed as the 4th parameter to the SQLIteOpenHelper sub-class (aka the DatabaseHelper class).
After doing one of the above, rerun the App.
NOTE any existing data will be lost.
If data has to be retained then a fix is more complicated but would be based upon using ALTER TABLE statements.
I am working on an MVC3 application database first approach . I would like to use one connection string to connect to database, based on some string (company name). Example: I have in my MSSQL Express 2012 this db: my_database_microsoft, my_database_oracle and so on..(those databases have same structure). On login page I have 3 input fields: username,password,company. I know how to build connection string dynamic with SqlConnectionStringBuilder and then use it on EntityConnectionStringBuilder
string providerName = "System.Data.SqlClient";
string serverName = "MY-PC\\SQL2012";
string databaseName = "my_database_"+form[company].toString();
.....
.....
entityBuilder.Provider = providerName;
// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = providerString;
// Set the Metadata location.
entityBuilder.Metadata =#"res://*/Models.Model1.csdl|res://*/Models.Model1.ssdl|res://*/Models.Model1.msl";
using (EntityConnection conn =
new EntityConnection(entityBuilder.ToString()))
{
conn.Open();
// Console.WriteLine("Just testing the connection.");
conn.Close();
}
obracun_placEntities1.nameOrConnectionString = entityBuilder.ToString();
obracun_placEntities1 o = new obracun_placEntities1(entityBuilder.ToString());
I have made a partial class of my entety and give a constructor that take a nameOrConnectionString string as a parameter.
public partial class obracun_placEntities1
{
public string nameOrConnectionString { get; set; }
public obracun_placEntities1(string nameOrConnectionString)
: base(nameOrConnectionString ?? "obracun_placEntities1") { }
}
This works only in loginController but how can I use this in UsersController and all other controllers where I using obracun_placEntities1 db = new obracun_placEntities1(); > this take the default database from web.config. I would not like to save connection string to session or cookie and than pass it in every controler as a parameter.
private obracun_placEntities1 db = new obracun_placEntities1();
How can i achieve that i pass connection string in login controller and using this database in entire project.
One more problem occured when i want to use public static string nameOrConnectionString
and pass it to constructor. The problem is when I open application in Chrome and login as user1 I get all infromation from user1 database, but then I login in MS Explorere as user2 and get all data from user2 database. When i refresh chrome I get information from the user2 database not user1.
Model1.context.cs
public partial class obracun_placEntities1 : DbContext
{
public static string nameOrConnectionString { get; set; }
// public static string connection;
public obracun_placEntities1()
: base(nameOrConnectionString ?? "obracun_placEntities1")
{
}
Connecting to different Databases is best done using the DBconnection constructor on DBCOntext. If you look at the DBContext class you will see multiple constructor overloads. One allows the DBConnection to be supplied. So no entry in WEB.Config/App.Config is required.
See this post with sample code Same Context accessing different databases.
EDIT sample added:
public partial class obracun_placEntities1 : DbContext
{
// use THIS CONSTRUCTOR
protected obracun_placEntities1(DbConnection dbConnection, bool contextOwnsConnection)
: base(dbConnection, contextOwnsConnection)
{
}
}
}
// DONT USE THIS
// obracun_placEntities1.nameOrConnectionString = entityBuilder.ToString();
// obracun_placEntities1 o = new obracun_placEntities1(entityBuilder.ToString());`
// build the connection - note: it is NOT a connection string. it is a DBConnection!
conn = getDBConnection4SQLServer(DatabaseServer,Databasename)
obracun_placEntities1 o = new obracun_placEntities1(conn,true);
//====================================================================
public const string DefaultDataSource = "localhost";
public DbConnection getDBConnection4SQLServer(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;
}
I finnaly getting it to work with this code.
My LoginController
[HttpPost]
public ActionResult Index(UPORABNIK model, FormCollection form)
{....}
public obracun_placEntities1(EntityConnection entityConnection)
: base(entityConnection, false)
{
}
I call EntityConnection conn = GetEntityConnDbName("ServerName", "FirmName").
_entities = new obracun_placEntities1(conn, false);
var uporabniki = from r in _entities.UPORABNIK.Where(r => r.ime == uporabnik && r.geslo == geslo && danes <= r.veljavnost).ToList()
select r;
I get the firmName from the post form so this work only in LoginController.But how can I use this constructor in all other Controllers? I get firm name only once in LoginControler, I tried to save it as cookie but then i can not read it in the constructor.
In my other Controller I use the default controller again. How can I tranfer conn to other Controllers?
private obracun_placEntities1 db = new obracun_placEntities1();
I would like to call like this
private obracun_placEntities1 db = new obracun_placEntities1(conn);
Or is there some better way?
It seems that SQL Server has a fair amount of XML support. Mostly I've seen info regarding storing XML in SQL Server, querying XML data stored in SQL Server, and exposing data as XML.
Is the following scenario an option:
I'd like to expose xml data (it's an RSS view of workitems) from a web site via a SQL Server view. The motivation is to create new computed values and then show the data via an SSRS report.
I'd like to use a view so that the data is always live, and avoid the need for a batch ETL.
Is this possible? What does the syntax look like?
using System;
using System.Data.Sql;
using Microsoft.SqlServer.Server;
using System.Collections;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Xml;
namespace RSSFunctions
{
public class GetRSSFeedClass
{
private class RSSRow
{
public SqlString Title;
public SqlString Description;
public RSSRow(SqlString Title, SqlString Description)
{
this.Title = Title;
this.Description = Description;
}
}
[SqlFunction(FillRowMethodName = "FillRSSRow")]
public static IEnumerable GetRSSFeed(SqlString RSSurl)
{
ArrayList RSSRowsCollection = new ArrayList();
string url = RSSurl.ToString();
WebRequest req = System.Net.WebRequest.Create(url);
WebResponse Res = req.GetResponse();
Stream rssStream = Res.GetResponseStream();
XmlDocument rssDoc = new XmlDocument();
rssDoc.Load(rssStream);
XmlNodeList rssItems = rssDoc.SelectNodes("rss/channel/item");
String Title = "";
String Description = "";
int i = 0;
for (i = 0; i <= rssItems.Count - 1; i++)
{
XmlNode rssDetail = default(XmlNode);
Title = "";
rssDetail = rssItems.Item(i).SelectSingleNode("title");
if (rssDetail.Equals(null) == false)
{
Title = rssDetail.InnerText;
}
Description = "";
rssDetail = rssItems.Item(i).SelectSingleNode("description");
if (rssDetail.Equals(null) == false)
{
Description = rssDetail.InnerText;
}
if (Title.Length > 97)
{
Title = Title.Substring(0, 97) + "...";
}
if (Description.Length > 3997)
{
Description = Description.Substring(0, 3997) + "...";
}
if (!string.IsNullOrEmpty(Title) && !string.IsNullOrEmpty(Description))
{
RSSRowsCollection.Add(new RSSRow(new SqlString(Title), new SqlString(Description)));
}
}
return RSSRowsCollection;
}
public static void FillRSSRow(object obj, out SqlString Title, out SqlString Description)
{
RSSRow _RSSRow = (RSSRow)obj;
Title = _RSSRow.Title;
Description = _RSSRow.Description;
}
SSMS
--ALTER DATABASE [dbname] TRUSTWORTHY ON
--go
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'RSSData')
DROP VIEW RSSData
go
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'fncCLRGetRSSFeed')
DROP FUNCTION fncCLRGetRSSFeed
go
IF EXISTS (SELECT name FROM sys.assemblies WHERE name = 'CLRRSSAssembly')
DROP ASSEMBLY CLRRSSAssembly
go
CREATE ASSEMBLY CLRRSSAssembly FROM 'C:\RSSAssembly.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS
GO
CREATE FUNCTION fncCLRGetRSSFeed(#url nvarchar(100))
RETURNS TABLE (
Title nvarchar(100),
[Description] nvarchar(4000)
)
AS EXTERNAL NAME CLRRSSAssembly.[RSSFunctions.GetRSSFeedClass].GetRSSFeed
go
CREATE VIEW RSSData
AS
SELECT * FROM fncCLRGetRSSFeed(N'http://channel9.msdn.com/Feeds/RSS/')
go
SELECT * FROM RSSData
Create a CLR proc to pull the live feed