I've recently started working with EF6 So my knowledge on it isn't very great. I am currently working on test web project which I have created using VS Express 2013. EF has created the required tables. Now I've added my own table which has basic information such as:
FirstName
Surname
DOB
What I'm trying to gather is would I write a SQL query in my function to get the data from the database so something like
using (SqlConnection connection = new SqlConnection(myConnectionString))
{
using (SqlCommand cmd = new SqlCommand("select * from my table", connection))
{
connection.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
//Read Data
}
}
}
Or is there a separate way to write it in EF? Because I couldn't find how and where the SQL syntax queries are used in EF or maybe I'm just missing something? Thanks in advance for your help & support
Entity Framework (EF) is an object-relational mapper that enables .NET
developers to work with relational data using domain-specific objects.
It eliminates the need for most of the data-access code that
developers usually need to write.
You need to review more there http://msdn.microsoft.com/en-gb/data/ef.aspx and at least read some intros to EF or some video tutorials.
var context = new EntitiesContext();//DbContext Object
var list = ent.Customers; // will return all customers.
The code you have posted is using ADO.Net. You can perform raw sql in entity framework like this
Entities ent = new Entities();//DbContext Object
var list = ent.tablename.SqlQuery("select * from my table");
And using Entity framework to get data from db
Entities ent = new Entities();//DbContext Object
var data = ent.tableName;
The point of EF is that you don't have to write SQL queries. You have an object model you use to access the database:
using (var context = new YourEntities())
{
var records = context.Table; // .Where(t => t.Name == "foo")
foreach (var record in records)
{
// ...
}
}
Please check out the Quickstart example from MSDN
http://msdn.microsoft.com/en-us/library/vstudio/bb399182%28v=vs.100%29.aspx
Related
I want a list of tables that exists on sqlite database, and well I've got a simple query that looks like:
SELECT name from sqlite_master WHERE type='table';
But now I need to execute this using entity framework core, so I am binding this to DataContext, and here is where I am stuck as data context contains all representation of tables as db set but not sqlite system tables, I tried using query on exposed database facade but it is not returning any pother values then number of rows it has affected, something like:
using (var ctx = new DataContext())
{
var query = #"SELECT name from sqlite_master WHERE type='table';"
string[] result = ctx.Database.ExecuteSqlCommand(query);
return result;
}
Is there any other way i can that information.
You can directly use ADO.NET commands with EntityFrameworkCore
using (var ctx = new DataContext())
{
using (var command = ctx.Database.GetDbConnection().CreateCommand())
{
command.CommandText = "SELECT name from sqlite_master WHERE type='table'";
ctx.Database.OpenConnection();
using (var result = command.ExecuteReader())
{
while (result.Read())
{
Console.WriteLine(result.GetString(0));
}
}
}
}
In case you need a schema with a list of tables inside the database you can always do:
using (var ctx = new DataContext())
{
DataTable dbSchemaWithTables = ctx.Database.GetDbConnection().GetSchema("Tables");
}
SQL Server provides output for inserted and updated record with the 'inserted' keyword.
I have a table representing a processing queue. I use the following query to lock a record and get the ID of the locked record:
UPDATE TOP (1) GlobalTrans
SET LockDateTime = GETUTCDATE()
OUTPUT inserted.ID
WHERE LockDateTime IS NULL
This will output a column named ID with all the updated record IDs (a single ID in my case). How can I translate this into EF in C# to execute the update and get the ID back?
Entity Framework has no way of doing that.
You could do it the ORM way, by selecting all the records, setting their LockDateTime and writing them back. That probably is not safe for what you want to do because by default it's not one single transaction.
You can span your own transactions and use RepeatableRead as isolation level. That should work. Depending on what your database does in the background, it might be overkill though.
You could write the SQL by hand. That defeats the purpose of entity framework, but it should be just as safe as it was before as far as the locking mechanism is concerned.
You could also put it into a stored procedure and call that. It's a little bit better than the above version because at least somebody will compile it and check that the table and column names are correct.
Simple Example #1 to get a data table:
I did this directly against the connection:
Changed the command.ExecuteNonQuery() to command.ExecuteReader()
var connection = DbContext().Database.Connection as SqlConnection;
using (var command = connection.CreateCommand())
{
command.CommandText = sql;
command.CommandTimeout = 120;
command.Parameters.Add(param);
using (var reader = command.ExecuteReader())
{
var resultTable = new DataTable();
resultTable.Load(reader);
return resultTable;
}
}
FYI, If you don't have an OUTPUT clause in your SQL, it will return an empty data table.
Example #2 to return entities:
This is a bit more complicated but does work.
using a SQL statement with a OUTPUT inserted.*
var className = typeof(T).Name;
var container = ObjContext().MetadataWorkspace.GetEntityContainer(UnitOfWork.ObjContext().DefaultContainerName, DataSpace.CSpace);
var setName = (from meta in container.BaseEntitySets where meta.ElementType.Name == className select meta.Name).First();
var results = ObjContext().ExecuteStoreQuery<T>(sql, setName, trackingEnabled ? MergeOption.AppendOnly : MergeOption.NoTracking).ToList();
T being the entity being worked on
How can I use dynamic queries in C# ? From what I've searched its similiar to when we use SqlCommand with parameters to prevent sql injection(example below).
using (SQLiteConnection DB_CONNECTION = new SQLiteConnection(connectionString))
{
DB_CONNECTION.Open();
string sqlquery = "UPDATE table SET Name =#Name, IsComplete=#IsComplete WHERE Key =#Key;";
int rows = 0;
using (SQLiteCommand command = new SQLiteCommand(sqlquery, DB_CONNECTION))
{
SQLiteParameter[] tableA = { new SQLiteParameter("#Key", todo.Key), new SQLiteParameter("#Name", table.Name), new SQLiteParameter("#IsComplete", table.IsComplete) };
command.Parameters.AddRange(tableA);
rows = command.ExecuteNonQuery();
}
DB_CONNECTION.Close();
return (rows);
}
I'm new to c# and i wondering how can I make this work, thanks in advance.
Basically just build up the string sqlQuery based on a set of conditions and ensure that the appropriate parameters have been set. For example, here is some psuedo-C# (not tested for bugs):
//Set to true, so our queries will always include the check for SomeOtherField.
//In reality, use some check in the C# code that you would want to compose your query.
//Here we set some value we want to compare to.
string someValueToCheck = "Some value to compare";
using (SQLiteConnection DB_CONNECTION = new SQLiteConnection(connectionString))
{
DB_CONNECTION.Open();
string sqlquery = "UPDATE MyTable SET Name =#Name, IsComplete=#IsComplete WHERE Key =#Key";
//Replace this with some real condition that you want to use.
if (!string.IsNullOrWhiteSpace(someValueToCheck))
{
sqlquery += " AND SomeOtherField = #OtherFieldValue"
}
int rows = 0;
using (SQLiteCommand command = new SQLiteCommand(sqlquery, DB_CONNECTION))
{
//Use a list here since we can't add to an array - arrays are immutable.
List<SQLiteParameter> tableAList = {
new SQLiteParameter("#Key", todo.Key),
new SQLiteParameter("#Name", table.Name),
new SQLiteParameter("#IsComplete", table.IsComplete) };
if (!string.IsNullOrWhiteSpace(someValueToCheck)) {
//Replace 'someValueToCheck' with a value for the C# that you want to use as a parameter.
tableAList.Add(new SQLiteParameter("#OtherFieldValue", someValueToCheck));
}
//We convert the list back to an array as it is the expected parameter type.
command.Parameters.AddRange(tableAList.ToArray());
rows = command.ExecuteNonQuery();
}
DB_CONNECTION.Close();
return (rows);
}
In this day and age it would probably be worth looking into LINQ to Entities, as this will help you to compose queries dynamically in your code - for example https://stackoverflow.com/a/5541505/201648.
To setup for an existing database - also known as "Database First" - see the following tutorial:
https://msdn.microsoft.com/en-au/data/jj206878.aspx
You can skip step 1 since you already have a database, or do the whole tutorial first as practice.
Here is some psuedo-C# LINQ code to perform roughly the same update as the previous example:
//The context you have setup for the ERP database.
using (var db = new ERPContext())
{
//db is an Entity Framework database context - see
//https://msdn.microsoft.com/en-au/data/jj206878.aspx
var query = db.MyTable
.Where(c => c.Key == todo.Key);
if (!string.IsNullOrWhiteSpace(someValueToCheck))
{
//This where is used in conjunction to the previous WHERE,
//so it's more or less a WHERE condition1 AND condition2 clause.
query = query.Where(c => c.SomeOtherField == someValueToCheck);
}
//Get the single thing we want to update.
var thingToUpdate = query.First();
//Update the values.
thingToUpdate.Name = table.Name;
thingToUpdate.IsComplete = table.IsComplete;
//We can save the context to apply these results.
db.SaveChanges();
}
There is some setup involved with Entity Framework, but in my experience the syntax is easier to follow and your productivity will increase. Hopefully this gets you on the right track.
LINQ to Entites can also map SQL stored procedures if someone one your team objects to using it for performance reasons:
https://msdn.microsoft.com/en-us/data/gg699321.aspx
OR if you absolutely ust compose custom queries in the C# code this is also permitted in Entity Framework:
https://msdn.microsoft.com/en-us/library/bb738521(v=vs.100).aspx
Before Entity Framework, if I had something like a stock quantity or an on order quantity for a product, I would update it's quantities using the current database values as such:
UPDATE Products SET AvailableQty = AvailableQty - 2 WHERE ProductId = 1;
Is there a way to accomplish the same thing with Entity Framework? It seems like the framework follows a Load, Modify, Update pattern:
Product product = db.Products.FirstOrDefault(x => x.ProductId == 1);
product.AvailableQty += 2;
db.SaveChanges();
However, following this method there is a possibility that the product changes between the initial loading of the data and the update of the data. I know I can have a concurrency field on the entity that will prevent the update, but in most cases I don't want to have user intervention (such as a customer placing an order or receiving a purchase order).
Is there a preferred method to handling situations like these using EF, or should I just fall back to raw SQL for these scenarios?
Enclose your find and update within a transaction
using (var transaction = new System.Transactions.TransactionScope())
{
Product product = db.Products.FirstOrDefault(x => x.ProductId == 1);
product.AvailableQty += 2;
db.SaveChanges();
transaction.Complete();
}
"preferred method" would be opinion-based, so I'll just concentrate on the answer. EF allows you direct access to the database through the DbContext's Database property. You can execute SQL directly with ExecuteSqlCommand. Or, you can use the SqlQuery extension method.
ExecuteSqlCommand returns the records affected. And, the SqlQuery extension methods lets you use the fill provided by EF.
Also, if that is not enough power, you can create your own commands like this:
var direct = mydbContext.Database;
using (var command = direct.Connection.CreateCommand())
{
if (command.Connection.State != ConnectionState.Open)
{
command.Connection.Open();
}
command.CommandText = query.ToString(); // Some query built with StringBuilder.
command.Parameters.Add(new SqlParameter("#id", someId));
using (var reader = command.ExecuteReader())
{
if (reader.Read())
{
... code here ...
reader.Close();
}
command.Connection.Close();
}
}
I'm using MiniProfiler to profile my sql commands.
One issue I'm dealing with now is repeated INSERT statements generated by linq.
I've converted them into a SqlBulkCopy command, however now it doesn't appear to record it in the sql view in MiniProfiler.
Would there even be an associated command string for a SqlBulkCopy?
Is it possible to get the bulk copy to appear in the list of sql commands?
Can I at least make it counted in the % sql bit?
I'm aware I could use MiniProfiler.Current.Step("Doing Bulk Copy") but that wouldn't count as SQL, and wouldn't show in the listing with any detail.
Current code below:
public static void BulkInsertAll<T>(this DataContext dc, IEnumerable<T> entities)
{
var conn = (dc.Connection as ProfiledDbConnection).InnerConnection as SqlConnection;
conn.Open();
Type t = typeof(T);
var tableAttribute = (TableAttribute)t.GetCustomAttributes(
typeof(TableAttribute), false).Single();
var bulkCopy = new SqlBulkCopy(conn)
{
DestinationTableName = tableAttribute.Name
};
//....
bulkCopy.WriteToServer(table);
}
You should be able to use CustomTimings to profile these. These are included in the new v3 version that is now available on nuget.
You can see some example usages of CustomTiming in the sample project where this is used to record http and redis events.
An example of how you could use it with SqlBulkCopy:
string sql = GetBulkCopySql(); // what should show up for the SqlBulkCopy event?
using (MiniProfiler.Current.CustomTiming("SqlBulkCopy", sql))
{
RunSqlBulkCopy(); // run the actual SqlBulkCopy operation
}