I made WPF app which uses Entity Framework and SQLite. At the beggining I loaded my database via ADO.NET Entity Data Model. Everything was working quite good but now I want to add option for users to choose from local files with database (all tables in databases should be the same but data could be diffrent for diffrent files). So to test this solution I copied my database file and made some changes in code:
I edited DbContext file by adding: (I found this here https://stackoverflow.com/a/23105811)
public appDBEntities(string filename)
: base(new SQLiteConnection() { ConnectionString =
new SQLiteConnectionStringBuilder()
{ DataSource = filename, ForeignKeys = true }
.ConnectionString }, true)
{
}
The users is selecting database file by using this function:
private void testButton_Click(object sender, RoutedEventArgs e)
{
// Create OpenFileDialog
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
// Set filter for file extension and default file extension
dlg.DefaultExt = ".db";
dlg.Filter = "Database files (*.db)|*.db";
// Display OpenFileDialog by calling ShowDialog method
Nullable<bool> result = dlg.ShowDialog();
// Get the selected file name
if (result == true)
{
// Open document
publicVariables.databasePath = dlg.FileName;
}
}
Than i want to test if everything is ok by displaying some data from database with this function:
public static void showParticipants(DataGrid participantsDataGrid, string connectionString)
{
using (var db = new appDBEntities(connectionString))
{
var query = from c in db.Participant
join gender in db.Sex on c.Sex equals gender.id
join club in db.Club on c.Club equals club.id
join nation in db.Nation on c.Nationality equals nation.id
select c.id;
var data = query.ToList();
participantsDataGrid.ItemsSource = data;
db.Dispose();
}
}
Like this:
showParticipants(testDataGrid, publicVariables.databasePath);
But this function
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
Is throwing this exception:
The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development. This will not work correctly. To fix this problem do not remove the line of code that throws this exception. If you wish to use Database First or Model First, then make sure that the Entity Framework connection string is included in the app.config or web.config of the start-up project. If you are creating your own DbConnection, then make sure that it is an EntityConnection and not some other type of DbConnection, and that you pass it to one of the base DbContext constructors that take a DbConnection. To learn more about Code First, Database First, and Model First see the Entity Framework documentation >here:http://go.microsoft.com/fwlink/?LinkId=394715
I have a similar task working by changing config entry, maybe it would work for you:
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var connectionStringsSection = (ConnectionStringsSection)config.GetSection("connectionStrings");
connectionStringsSection.ConnectionStrings["DbStatisticsEntities"].ConnectionString =
"metadata=res://*/Models.DbStatisticsModel.csdl|res://*/Models.DbStatisticsModel.ssdl|res://*/Models.DbStatisticsModel.msl;provider=System.Data.SQLite.EF6;provider connection string='data source=" + this.DBFileName + "'";
connectionStringsSection.ConnectionStrings["DbStatisticsEntities"].ProviderName = "System.Data.EntityClient";
config.Save();
ConfigurationManager.RefreshSection("connectionStrings");
Properties.Settings.Default.Save();
Properties.Settings.Default.Reload();
Related
I have developed an accounting program that is working beautifully, but now a new need has arisen.
When I enter the program, by default it reads the DB that I put in the file WinSCM.exe.config and if I want to change I have to exit the program and edit the file changing the DB name.
I did not want it to be this way, because my client does accounting for several companies and each company is a DB, so I wanted a way to select a company and when selecting this company the database is automatically changed in the release version.
I'm using Entity Framework to connect to Sql Server DB
Can someone help me?
I'm not sure what reading your DB is, but normally when you use Entity Framework you create a DbContext object whenever you need to do a query, or at utmost a few queries. You are not supposed to keep this DbContext alive for longer periods of time, say more than a few seconds. A minute would be very rare.
Whenever you create the Dbcontext instance you could use the default constructor that uses the config file to get the connection string to the database.
However one of the other constructors let you define the connection string to the database in the constructor. So if you want to construct your DbContext and connect it to a different database, just use that constructor
If you don't know the connection string, but you have a DbConnection to the database, there will be even a constructor for this case.
Hi Everybody Thank alot for your Answer. I just Solved My Question like this:
Fisrt of all, I created a class wich I called ConnetionTolls with this Content://.
public static class ConnectionTools
{
// all params are optional
public static void ChangeDatabase(
this DbContext source,
string initialCatalog = "",
string dataSource = "",
string userId = "",
string password = "",
bool integratedSecuity = true,
string configConnectionStringName = "")
/* this would be used if the
* connectionString name varied from
* the base EF class name */
{
try
{
// use the const name if it's not null, otherwise
// using the convention of connection string = EF contextname
// grab the type name and we're done
var configNameEf = string.IsNullOrEmpty(configConnectionStringName)
? source.GetType().Name
: configConnectionStringName;
// add a reference to System.Configuration
var entityCnxStringBuilder = new EntityConnectionStringBuilder
(System.Configuration.ConfigurationManager
.ConnectionStrings[configNameEf].ConnectionString);
// init the sqlbuilder with the full EF connectionstring cargo
var sqlCnxStringBuilder = new SqlConnectionStringBuilder
(entityCnxStringBuilder.ProviderConnectionString);
// only populate parameters with values if added
if (!string.IsNullOrEmpty(initialCatalog))
sqlCnxStringBuilder.InitialCatalog = initialCatalog;
if (!string.IsNullOrEmpty(dataSource))
sqlCnxStringBuilder.DataSource = dataSource;
if (!string.IsNullOrEmpty(userId))
sqlCnxStringBuilder.UserID = userId;
if (!string.IsNullOrEmpty(password))
sqlCnxStringBuilder.Password = password;
// set the integrated security status
sqlCnxStringBuilder.IntegratedSecurity = integratedSecuity;
// now flip the properties that were changed
source.Database.Connection.ConnectionString
= sqlCnxStringBuilder.ConnectionString;
}
catch (Exception ex)
{
// set log item if required
}
}
********the way to use it is like this***************
//I use this method in a diferent Class
//This method returns the Entity i use with new connections
public static MyEntities SelectDb(String DataBase,String sqlUser,String pw, String serverInstance){
var selectedDbase = new MyEntities();
// so only reference the changed properties
// using the object parameters by name
selectedDbase.ChangeDatabase
(
initialCatalog: DataBase,
userId: sqlUser,
password: pw,
dataSource: serverInstance// could be ip address 100.23.45.67 etc
);
return selectedDbase;
}
I want to thank everyone here and on other forums because this was the result of Your Contributions
how can i fill the gridlookupedit correctly?.
I can not find the error.
Method fill gridlookupedit
public void CargaGLEVerdadero()
{
pcbjEntidades contexto = new pcbjEntidades();
IList consultaModeloInsumosVerdadera = (from ModeloInsumoes in contexto.ModeloInsumoes
where
ModeloInsumoes.Activo == true
select new
{
ModeloInsumoes.NombreModeloInsumo
}).ToList();
gleNombreModelo.Properties.DataSource = new BindingSource(consultaModeloInsumosVerdadera, "");
}
Construct of form
public frmAgregarMarca()
{
InitializeComponent();
CargaGLEVerdadero();
}
This issue does not related to GridLookup directly rather the to the EF/Winforms interoperation.
Since you are using DevExpress, you can use the Data Source Configuration Wizard.This feature is available for any data-aware control in threir suite and it knows how to do the things correctly and it can make all the work for you:
// This line of code is generated by Data Source Configuration Wizard
// Instantiate a new DBContext
WindowsFormsApplication2.CountriesDBEntities dbContext = new WindowsFormsApplication2.CountriesDBEntities();
// Call the Load method to get the data for the given DbSet from the database.
dbContext.Countries.Load();
// This line of code is generated by Data Source Configuration Wizard
gridLookUpEdit1.Properties.DataSource = dbContext.Countries.Local.ToBindingList();
Then you can customize Wizard's output:
dbContext.Countries.Where(c => c.Capital.StartsWith("A")).Load();
The compiler is giving me this error:
An attempt to attach an auto-named database for file failed. A database with the same name exists or specified file cannot be open, or it is located on UNC share.
I've been reading around other stackoverflow posts and they mention it might be a connectionstring problem, but I'm coding this in linq, not ado.net code. I don't use a traditional connectionstring. In fact, I had to use a namespace to call the tableAdapter in order for me to access the data source I needed.
The code being used is as follows:
using CustomerInvoices.MMABooksDataSetTableAdapters;
namespace CustomerInvoices
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
MMABooksDataSet mmaBooksDataSet = new MMABooksDataSet();
InvoicesTableAdapter invoicesTableAdapter = new InvoicesTableAdapter();
CustomersTableAdapter customersTableAdapter =
new CustomersTableAdapter();
private void Form1_Load(object sender, EventArgs e)
{
invoicesTableAdapter.Fill(mmaBooksDataSet.Invoices);
customersTableAdapter.Fill(mmaBooksDataSet.Customers);
var invoices = from invoice in mmaBooksDataSet.Invoices
join customer in mmaBooksDataSet.Customers
on invoice.CustomerID equals customer.CustomerID
orderby customer.Name, invoice.InvoiceTotal descending
select new
{
customer.Name,
invoice.InvoiceID,
invoice.InvoiceDate,
invoice.InvoiceTotal
};
string customerName = "";
int i = 0;
foreach (var invoice in invoices)
{
if (invoice.Name != customerName)
{
lvInvoices.Items.Add(invoice.Name);
customerName = invoice.Name;
}
else
{
lvInvoices.Items.Add("");
}
lvInvoices.Items[i].SubItems.Add(invoice.InvoiceTotal.ToString());
lvInvoices.Items[i].SubItems.Add(Convert.ToDateTime
(invoice.InvoiceDate).ToShortDateString());
lvInvoices.Items[i].SubItems.Add
(invoice.InvoiceTotal.ToString("c"));
i += 1;
}
}
}
}
I figured it out. Thru the data source, I went into the connection property window and found the connection path file, I changed it to the correct one
Data Source=localhost\sqlexpress;Initial Catalog=MMABooks;Integrated Security=True
And it Worked. It seems the error is because the connectionString was pointing to the wrong path file. Hope this helps others. Thank you.
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;
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.