The Entity Framework Code First API includes methods that enable you to pass SQL commands directly to the database. You have the following options:
- Use the DbSet.SqlQuery method for queries that return entity types. The returned objects must be of the type expected by the
DbSet
object, and they are automatically tracked by the database context unless you turn tracking off. (See the following section about the AsNoTracking method.) - Use the Database.SqlQuery method for queries that return types that aren't entities. The returned data isn't tracked by the database context, even if you use this method to retrieve entity types.
- Use the Database.ExecuteSqlCommand for non-query commands.
在 web 应用程序中执行 SQL 命令,您必须采取预防措施,以保护您的网站防止 SQL 注入攻击。一个办法就是使用参数化的查询,以确保提交的 web 页的字符串不能被解释为 SQL 命令。
==============================================================
调用一个查询,返回实体
string sql = "select * from users where uIsDel=@p0";
List
exec sp_executesql N'select * from users where uIsDel=@p0',N'@p0 nvarchar(1)',@p0=N'0'
与如下语句相似
List
SELECT
[Extent1].[uId] AS [uId],
[Extent1].[uName] AS [uName],
[Extent1].[uLoginName] AS [uLoginName],
[Extent1].[uPwd] AS [uPwd],
[Extent1].[uAddtime] AS [uAddtime],
[Extent1].[uIsDel] AS [uIsDel]
FROM [dbo].[Users] AS [Extent1]
WHERE 0 = [Extent1].[uIsDel]
==============================================================
调用一个查询,返回其他类型的对象
// Commenting out LINQ to show how to do the same thing in SQL. //IQueryable= from student in db.Students // group student by student.EnrollmentDate into dateGroup // select new EnrollmentDateGroup() // { // EnrollmentDate = dateGroup.Key, // StudentCount = dateGroup.Count() // };
//var data = db.Students.GroupBy(s => s.EnrollmentDate).Select(s => new EnrollmentDateGroup() { EnrollmentDate = s.Key, StudentCount = s.Count() }); // SQL version of the above LINQ code. string query = "SELECT EnrollmentDate, COUNT(*) AS StudentCount " + "FROM Person " + "WHERE Discriminator = 'Student' " + "GROUP BY EnrollmentDate"; IEnumerabledata = db.Database.SqlQuery (query);
复杂查询手写代码执行效率会更好。
============================================================
调用更新查询
ViewBag.RowsAffected= db.Database.ExecuteSqlCommand("UPDATE Course SET Credits = Credits * {0}", 2);
======================================================================================
不跟踪查询
Department duplicateDepartment = db.Departments
.Include("Administrator")
.Where(d => d.PersonID== department.PersonID)
.AsNoTracking()
.FirstOrDefault();
如果查询大量数据,且这些数据并不用于更新数据库,可以使用不跟踪查询。
如果从客户端绑定了实体类,并想直接用于更新,而之前因某些原因需要从数据库中读取相同主键记录到内存中进行处理,这时,读取记录应使用不跟踪查询,否则更新时会提示错误。
内存中的实体类是一个实体类的包装,里面包含许多用于维护数据的属性。
========================================================================================
查看 发送到数据库的SQL
publicActionResultIndex()
{
var courses = db.Courses;
var sql = courses.ToString();
returnView(courses.ToList());
}
publicActionResultIndex(int?SelectedDepartment)
{
var departments = db.Departments.OrderBy(q => q.Name).ToList();
ViewBag.SelectedDepartment=newSelectList(departments,"DepartmentID","Name",SelectedDepartment);
int departmentID =SelectedDepartment.GetValueOrDefault();
IQueryable<Course> courses = db.Courses
.Where(c =>!SelectedDepartment.HasValue|| c.DepartmentID== departmentID)
.OrderBy(d => d.CourseID)
.Include(d => d.Department);
var sql = courses.ToString();
returnView(courses.ToList());
}
sql变量就是要发送到数据库的sql语句。
====================================================================================
禁止创建代理 有时需要禁止实体框架创建代理实例。例如,人们通常认为序列化非代理实例要比序列化代理实例容易得多。可通过清除 ProxyCreationEnabled 标记来关闭代理创建功能。上下文的构造函数便是可执行此操作的一个位置。例如: public class BloggingContext : DbContext { public BloggingContext() { this.Configuration.ProxyCreationEnabled = false; } public DbSetBlogs { get; set; } public DbSet Posts { get; set; } } 请注意,在无需代理执行任何操作的情况下,EF 不会为类型创建代理。这意味着,也可以通过使用封装和/或没有虚拟属性的类型,避免生成代理。
====================================================================================
关闭自动变化探测
Entity Framework Automatic Detect Changes When using most POCO entities the determination of how an entity has changed (and therefore which updates need to be sent to the database) is handled by the Detect Changes algorithm. Detect Changes works by detecting the differences between the current property values of the entity and the original property values that are stored in a snapshot when the entity was queried or attached. The techniques shown in this topic apply equally to models created with Code First and the EF Designer. By default, the Entity Framework performs Detect Changes automatically when the following methods are called: DbSet.Find DbSet.Local DbSet.Remove DbSet.Add DbSet.Attach DbContext.SaveChanges DbContext.GetValidationErrors DbContext.Entry DbChangeTracker.Entries Disabling automatic detection of changes If you are tracking a lot of entities in your context and you call one of these methods many times in a loop, then you may get significant performance improvements by turning off detection of changes for the duration of the loop. For example: using (var context = new BloggingContext()) { try { context.Configuration.AutoDetectChangesEnabled = false; // Make many calls in a loop foreach (var blog in aLotOfBlogs) { context.Blogs.Add(blog); } } finally { context.Configuration.AutoDetectChangesEnabled = true; } } Don’t forget to re-enable detection of changes after the loop — We've used a try/finally to ensure it is always re-enabled even if code in the loop throws an exception. An alternative to disabling and re-enabling is to leave automatic detection of changes turned off at all times and either call context.ChangeTracker.DetectChanges explicitly or use change tracking proxies diligently. Both of these options are advanced and can easily introduce subtle bugs into your application so use them with care.
==============================================================================