Managed Entity Framework not generating stored procedures mappings - c#

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.

Related

Filter Record Set Before Populating ADO.NET Object

I used this tutorial to build a Crystal Report in my application. The tutorial guides the user through developing an ADO.NET object and then populating it with data. I am also using a Parameter in the Crystal Report to limit the data set. The issue I'm having is that loading the report is slow and I wonder if it's because I have to load more data than I actually need before the Crystal Report employs the Parameter filter.
Following is my existing code, which runs on the report viewer form Load event. I'd like to adjust the code below to pass a parameter so I can filter the data as it's loaded rather than loading a bunch of data I know I won't need or use.
private void InspectionReportSerial2_Viewer_Load(object sender, EventArgs e)
{
International_PZD_PRDEntities db = new International_PZD_PRDEntities();
var list = db.vw_Nightly_and_Inspections.Select(p=>new {ID = p.ID,
SerialNumber = p.SerialNumber, ProductionOrder = p.ProductionOrder,
Product=p.Product, Customer=p.Customer, SalesOrder = p.SalesOrder,
LineItem = p.LineItem, Section=p.Section,InspectionPoint=p.InspectionPoint,
Status=p.Status,SectionSignoffBy = p.SectionSignoffBy,
SectionSignoffCheck=p.SectionSignoffCheck,
SectionSignoffDate = p.SectionSignoffDate,HardwareSerial=p.HardwareSerial,
SectionSortString = p.SectionSortString, ItemSortString = p.ItemSortString,
Comment = p.Comment});
InspectionReportSerial21.SetDataSource(list);
}
Add a Where. Since you are not describing the kind of filtering you need, I can only give an example:
private void InspectionReportSerial2_Viewer_Load(object sender, EventArgs e)
{
International_PZD_PRDEntities db = new International_PZD_PRDEntities();
var list = db.vw_Nightly_and_Inspections
.Where(p => p.Customer == "Dekxblock")
.Select(p => new { ID = p.ID, SerialNumber = p.SerialNumber, ... });
InspectionReportSerial21.SetDataSource(list);
}
I don't know what International_PZD_PRDEntities is. If it is some kind of O/R-mapper (e.g., EF or EF Core), then this will filter the records on the database side, which is faster than filtering the data in your application, because less records have to be transmitted. If not, then you should execute a query like SELECT * FROM vw_Nightly_and_Inspections WHERE Customer = 'Dekxblock' including the filter. Make sure to use Command.Parameters

'Link Table Manager' functionality Programatically using c#

I want to write some custom code to perform the 'Link Table Manager' operation programatically. I have MS-Access database which is currently referencing external data from Excel,MS-Access and SQL server.
Before executing a Macro on my MS-Access database, I want to re-link the external data sources or provide new location of the data-source in case there is change in the location of the data source.
I have a table in MS-Access database which is Linked to an external SQL data source(Test database). Now I want it to be linked to Production Database. I have tried the following code but it is throwing a COM-Exception with error description as 'ODBC--connection to 'EmployeeConnectionForSQL' failed.'
public void performLinkTableMangerOperationForSQL()
{
string CurrentDatabasePath = #"D:\UDTDatabase\InternalDatabase.accdb";
Microsoft.Office.Interop.Access.Dao.DBEngine DAO = new Microsoft.Office.Interop.Access.Dao.DBEngine();
Microsoft.Office.Interop.Access.Dao.Database db;
Microsoft.Office.Interop.Access.Dao.TableDefs dt;
db = DAO.OpenDatabase(CurrentDatabasePath);
dt = db.TableDefs;
// Refreshing link for Sql server external table with DSN.
string sqlSource = #"DATABASE=Employee;";
string DSNName = "EmployeeConnectionForSQL;";
string sqlNewConnectionString = #"ODBC;FileDSN=" + DSNName + sqlSource;
foreach (Microsoft.Office.Interop.Access.Dao.TableDef table in dt)
{
string name = table.Name;
if (table.Name == "dbo_Employees")
{
table.Connect = sqlNewConnectionString;
table.RefreshLink();
}
}
db.Close();
}
That FileDSN is clearly invalid. A FileDSN should point to a .dsn file. If you want to use a normal DSN, use DSN=, not FileDSN=. Since there's an invalid DSN, you can't relink.
I highly recommend you go DSNless, and just use a connection string, but providing a valid FileDSN should work too.

I can query mysql DB but not save changes to it

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();
}

Entity framework Context.SaveChanges not working at all

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;

Best practice to create (on demand) SQL Server 2008 Express databases in C#?

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.

Categories