I had created a system using Visual Studio 2015 with a SQLServer database, i could query the DB but not save changes to it. So i created the database inside Visual Studio. I now tried to create the database in MySQL workbench and have the same issue. I switched to mysql as i was unsure if i had correctly installed My SQL Server, i have definately installed mysql properly as i have used it for projects in Java.
I created the database using a code first technique and this worked fine. Any ideas?
Connection String from appsettings
"DataAccessMySqlProvider": "server=localhost;port=3306;database=rentalsdb;userid=root;password=******"
In Startup.cs
var sqlConnectionString = Configuration.GetConnectionString("DataAccessMySqlProvider");
services.AddMvc();
services.AddDbContext<RentalsDbContext>(options =>
options.UseMySQL(
sqlConnectionString,
b => b.MigrationsAssembly("RentalsRated.Web")));
services.AddDbServiceDependencies(sqlConnectionString);
In my repo then
public bool CreateUser(UserAccount user)
{
if (user != null)
{
try
{
_Context.UserAccounts.Add(user);
_Context.Entry(user).State = EntityState.Modified;
_Context.SaveChanges();
return true;
}
catch ....
I can see the right variables come to here. It all worked fine with the database in visual studios server explorer.
Thanks!
IndexOutOfRangeException: Index was outside the bounds of the array.
The Stack trace: at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(Tuple2 parameters)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList1 entriesToSave)...
UPDATE: Works when i comment out my data that is being passed as Byte[].
Root cause:
Password and salt fields are defined as blobs. Change the type of the password and salt fields to one of the string types instead.
Masking issue:
You were changing the state of the entity to Modifed right after adding it to the table which might corrupt the internal state of the context.
MSDN is recommending two different ways of adding new entity to the context
https://msdn.microsoft.com/en-us/library/jj592676(v=vs.113).aspx
1) By adding the entity directly to the table.
using (var context = new BloggingContext())
{
var blog = new Blog { Name = "ADO.NET Blog" };
context.Blogs.Add(blog);
context.SaveChanges();
}
2) By changing the state of the entity to Added
using (var context = new BloggingContext())
{
var blog = new Blog { Name = "ADO.NET Blog" };
context.Entry(blog).State = EntityState.Added;
context.SaveChanges();
}
Related
I'm working on a project that uses EFCore 2.1.0-preview1-final code first approach. Like in EF6 (and previous versions) I want to ensure the compatibility of my DbContext (and models) to the database.
In EF6 it was enabled by default and it was possible to deactivate it with Database.CompatibleWithModel(false);. As far as I know EF uses the __MigrationHistory table where the model information was stored. EFCore has no such column in __EFMigrationsHistory table that could provide such information.
I cannot find any information about compatibility check in EFCore. But I want to ensure the compatibility, because after some tests it seems not to be enabled by default (or does exist). I tested it by adding and deleting some columns from database manually and executing the application after the modifications. I - against my expectation - received no exception.
Does anybody know how to achieve a compatibility check from model to database and vice versa like in EF6 for EFCore?
Or could provide some helpful links for further information about it or why it doesn't exist in EFCore (because it is not necessary)?
I strongly advise against doing this since it uses internal components and is error-prone, but here's one way to do it.
using (var db = new MyDbContext())
{
var reporter = new OperationReporter(handler: null);
var designTimeServiceCollection = new ServiceCollection()
.AddSingleton<IOperationReporter>(reporter)
.AddScaffolding(reporter);
new SqlServerDesignTimeServices().ConfigureDesignTimeServices(designTimeServiceCollection);
var designTimeServices = designTimeServiceCollection.BuildServiceProvider();
var databaseModelFactory = designTimeServices.GetService<IScaffoldingModelFactory>();
var databaseModel = (Model)databaseModelFactory.Create(
db.Database.GetDbConnection().ConnectionString,
tables: new string[0],
schemas: new string[0],
useDatabaseNames: false);
var currentModel = db.Model;
// Fix up the database model. It was never intended to be used like this. ;-)
foreach (var entityType in databaseModel.GetEntityTypes())
{
if (entityType.Relational().Schema == databaseModel.Relational().DefaultSchema)
{
entityType.Relational().Schema = null;
}
}
databaseModel.Relational().DefaultSchema = null;
databaseModel.SqlServer().ValueGenerationStrategy =
currentModel.SqlServer().ValueGenerationStrategy;
// TODO: ...more fix up as needed
var differ = db.GetService<IMigrationsModelDiffer>();
if (differ.HasDifferences(databaseModel, currentModel))
{
throw new Exception("The database and model are out-of-sync!");
}
}
I'm having problems with this code. I´m able to connect to an mdf example database archive and generate the entity model. Althought I´m able to query the context model and retrieve information from the DB, when I try to update, delete or insert anything in the context and translate the changes to the DB Context.SaveChanges is not working. There is no Exception, the Entity model is updated properly, but the DB does not have the change.
Thanks in regard
public void addCourse(int courseId, int deptId, string courseTitle)
{
SchoolContexto = new SchoolEntities();
Course mycourse= new Course();
mycourse.CourseID = courseId;
mycourse.Credits = 10;
mycourse.DepartmentID = deptId;
mycourse.Title = courseTitle;
SchoolContexto.Courses.Add(mycourse);
SchoolContexto.SaveChanges();
SchoolContexto.Dispose();
}
Make property of .mdf file in your solution as
Copy to output Directory: "Copy only if newer"
Otherwise your db file will overwrite every time it runs
i suggest you to use this code :
public void addCourse(int courseId, int deptId, string courseTitle)
{
SchoolEntities entities = new SchoolEntities();
Course mycourse= new Course();
mycourse.CourseID = courseId;
mycourse.Credits = 10;
mycourse.DepartmentID = deptId;
mycourse.Title = courseTitle;
entities.Courses.Add(mycourse);
entities.SaveChanges();
}
if this is not working i suggest you to check your app.config file :)
Another way to add a new entity to the context is to change its state to Added. Have you tried this
using (var entities = new SchoolEntities())
{
Course mycourse= new Course();
mycourse.CourseID = courseId;
mycourse.Credits = 10;
mycourse.DepartmentID = deptId;
mycourse.Title = courseTitle;
context.Entry(mycourse).State = EntityState.Added;
entities.SaveChanges();
}
I think the Problem is that you working on localdb (.mdf) file .
I had the same problem but when i created new (sql server database connection)
Server name : (localdb)\MSSqlLocaldb .... it worked
A little off the subject but just in case you're here because you're performing an update and not an add, Check if you need a key on the table. I had a similar issue with EF Core. During an update on a table no error was generated but the SaveChanges returned 0. It wasn't until I tested adding a record, that it generated the key error. I resolved the key issue and the update went fine.
It happens because probably you don't have primary key in your Course entity.
I solved the problem by including the following namespace
using System.Data.SqlClient;
I've looked at so many posts about this, but still haven't found the solution:
I'm using a winforms app that uses EntityFramework (6?). When I load the form I can read from the DB using the context (Entities). However, when I savechanges after adding a new entity, it doesn't persist to the db.
var c = new Card { Name = tbName.Text, Quantity = int.Parse(tbQuantity.Text) };
dbContext.Cards.Add(c);
dbContext.SaveChanges();
The dbContext is setup in the form constructor and is an instance of "LiquorTrackEntities".
LiquorTrackEntities dbContext;
public Form1()
{
InitializeComponent();
dbContext = new LiquorTrackEntities()
Reading from the db works:
var cards = dbContext.Cards.ToList();
I do this stuff all the time in asp.net MVC, but it isn't working in WinForms.. is there something special I have to do in winforms? I also know about the normal "using (var db = new LiquorEntitiesEntities())" convention, but I just want to get this functioning before I worry about convention.
Any ideas?
Just tried this to no avail:
var c = new Card { Name = tbName.Text, Quantity = int.Parse(tbQuantity.Text) };
dbContext.Cards.Attach(c);
dbContext.Entry(c).State = EntityState.Added;
dbContext.SaveChanges();
Just tried creating a new EDMX using EF5 instead.. same problem.
UPDATE:
SaveChanges does return a 1 when after adding a card. It stays in the context (if I reload my cards from the context, the new one is there..) but never makes it to the database.
Please note that I am attempting to use stored procedures to insert and update table records. When I add the stored procedure to the database and update the *.edmx file, it sees the stored procedure I've added; however, I previously did the following with a different project:
var db = new MyMarinaEntities();
db.prBoatInsert(registrationNumber, manufacturer, modelYear, length, customerID);
Now, however, when I type "db." intellisense doesn't see the insert stored procedures. Also, when I search in the InlandMarinaEntities.Designer.cs file, it doesn't have any
public int prBoatUpdate(Nullable<global::System.Int32> boatID, global::System.String registrationNumber, global::System.String manufacturer, Nullable<global::System.Int32> modelYear, Nullable<global::System.Int32> length, Nullable<global::System.Int32> customerID)
function. Does anyone have any idea as to why it is not adding prBoatUpdate to the *.Designer.cs file?
Alternatively, I understand that MEF can generate Insert, Update and Delete operations for each table; however, when I generate the *.edmx file, I don't see any of these operations added, and I don't see any option to add them when going through the wizard to generate the *.edmx file. What am I missing? Please note that I am using Visual Studio 2010 and SQL Server 2008. TIA.
Please note that I determined how to add and update database items using the MEF auto-generated functions instead of using stored procedures. Here is how you load an object from the database:
private void LoadBoat(int boatID)
{
using (var db = new MyMarinaEntities())
{
var boat = db.Boats.SingleOrDefault(b => (b.BoatID == boatID));
this.chkIsRental.Checked = boat.IsRental;
this.chkInactive.Checked = boat.Inactive;
this.txtLength.Text = boat.Length;
this.txtManufacturer = boat.Manufacturer;
// ...
}
}
Here is how to save changes to the boat:
protected void btnSave_click(object sender, EventArgs args)
{
using (var dm = new MyMarinaEntities())
{
MyMarinaEntities boat;
boat.IsRental = this.chkIsRental.Checked;
boat.Inactive = this.chkInactive.Checked;
boat.Length = this.txtLength.Text;
boat.Manufacturer = this.txtManufacturer;
// ...
if (boatID.Value == "")
dm.AddObject("Boats", boat);
dm.SaveChanges();
}
}
So MEF not only saves you from writing lots of code for Object Relational Mapping (ORM), it also saves you from writing SQL code for stored procedures or commands.
The purpose is to handle the user's data (you can call them project, document, file, or whatever) in a brand new SQL Server 2008 Express database. The data are expected to occupy much less space than the 4GB available with the express edition (which is also free to distribute).
E.g., each time the user selects File->New command, a new empty database will be created at the specified location. On the other hand, a similar command, File->Open must provide support to retrieve the list of the databases to select one for opening.
So, the following issues must be resolved:
a) The application must be able to create the connection string and attach the database to SQL Server 2008 Express through code (C#)
b) The application must be able to retrieve (again through code) a list with all the available databases, to give the user a chance to select one to open.
I think it would be helpful to have a template database in resources and copy it in the location specified by the user.
Do you think it is a working solution? Do you have any suggestions?
There's lots you can do with Sql Server Management Objects (SMO):
// Add a reference to Microsoft.SqlServer.Smo
// Add a reference to Microsoft.SqlServer.ConnectionInfo
// Add a reference to Microsoft.SqlServer.SqlEnum
using Microsoft.SqlServer.Management.Smo;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
public class SqlServerController
{
private Server m_server = null;
public SqlServerController(string server)
{
m_server = new Server(server);
}
public void AttachDatabase(string database, StringCollection files,
AttachOptions options)
{
m_server.AttachDatabase(database, files, options);
}
public void AddBackupDevice(string name)
{
BackupDevice device = new BackupDevice(m_server, name);
m_server.BackupDevices.Add(device);
}
public string GetServerVersion(string serverName)
{
return m_server.PingSqlServerVersion(serverName).ToString();
}
public int CountActiveConnections(string database)
{
return m_server.GetActiveDBConnectionCount(database);
}
public void DeleteDatabase(string database)
{
m_server.KillDatabase(database);
}
public void DetachDatabase(string database, bool updateStatistics,
bool removeFullTextIndex)
{
m_server.DetachDatabase(database, updateStatistics, removeFullTextIndex);
}
public void CreateDatabase(string database)
{
Database db = new Database(m_server, database);
db.Create();
}
public void CreateTable(string database, string table,
List<Column> columnList, List<Index> indexList)
{
Database db = m_server.Databases[database];
Table newTable = new Table(db, table);
foreach (Column column in columnList)
newTable.Columns.Add(column);
if (indexList != null)
{
foreach (Index index in indexList)
newTable.Indexes.Add(index);
}
newTable.Create();
}
public Column CreateColumn(string name, DataType type, string #default,
bool isIdentity, bool nullable)
{
Column column = new Column();
column.DataType = type;
column.Default = #default;
column.Identity = isIdentity;
column.Nullable = nullable;
return column;
}
public Index CreateIndex(string name, bool isClustered, IndexKeyType type,
string[] columnNameList)
{
Index index = new Index();
index.Name = name;
index.IndexKeyType = type;
index.IsClustered = isClustered;
foreach (string columnName in columnNameList)
index.IndexedColumns.Add(new IndexedColumn(index, columnName));
return index;
}
}
An alternate solution is to use SQLite rather than SQL Express. You can even continue to use ADO.NET if you use this solution. SQLite databases are simply files, and your connection strings can refer to the file path. When a user wants to open their file, they can select an actual file.
I get the impression that this database will live locally on user's machine. If that's the case, sql server express is not usually a good database choice. It's a server-class engine rather than a desktop or in process engine. Instead, there are a number of good in process engines you can use: Sql Server Compact Edition, Sqlite (as mentioned by Jacob) or even Access.
If you believe SQL Server Express 2008 is the right choice (sqllite does seem to fit better though), I would look at using User Instances which will allow non-administrators to add databases from files as you describe.
This article shows how to create a new database, and attach it to a SQL Server database instance:
How to: Attach a Database File to SQL Server Express
http://msdn.microsoft.com/en-us/library/ms165673.aspx
These article shows how to manage the attaching and detaching of existing databases:
http://msdn.microsoft.com/en-us/library/ms190794.aspx
http://www.databasejournal.com/features/mssql/article.php/2224361/Attaching-and-Detaching-Databases-on-SQL-Server.htm
For the following connection string for SQL Server 2008 R2.
<connectionstring>Data Source=.\SQLEXPRESS;Initial Catalog=MyDatabase;Integrated Security=True;Pooling=True</connectionstring>
you can do
var connectionString = new SqlConnectionStringBuilder(connectionString);
var serverConnection = new ServerConnection("DatabaseInstanceName in server");
var serverInstance = new Server(serverConnection);
if (serverInstance.Databases.Contains(connectionString.InitialCatalog))
serverInstance.KillDatabase(connectionString.InitialCatalog);
var db = new Database(serverInstance, connectionString.InitialCatalog);
try
{
db.Create();
}
catch (SqlException ex)
{
throw;
}
Thanks to Mr. Harvey for pointing the right direction. Although in my case, I have to make these small changes. Because, I use the windows authentication.