ASP.NET Core3.X EF学习2 读取、更新数据

Include与ThenInclude

在这里面比较关注的是Include和ThenInclude语法

  var student = await _context.Students.Include(s => s.Enrollments)
                .ThenInclude(e => e.Course)
                .AsNoTracking()
                .FirstOrDefaultAsync(m => m.ID == id);

在这个例子中类似sql中的left join
先去查找Students的导航属性Enrollments,然后再去关联Enrollment的Course属性,进而获取到课程的相关信息
Include的用法,通过查看源码有以下几个用法

/// <summary>
    ///     Specifies related entities to include in the query results. The navigation property to be included is specified starting with the
    ///     type of entity being queried (<typeparamref name="TEntity" />). If you wish to include additional types based on the navigation
    ///     properties of the type being included, then chain a call to
    ///     <see cref="M:Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ThenInclude``3(Microsoft.EntityFrameworkCore.Query.IIncludableQueryable{``0,System.Collections.Generic.IEnumerable{``1}},System.Linq.Expressions.Expression{System.Func{``1,``2}})" />
    ///     after this call.
    /// </summary>
    /// <example>
    ///     <para>
    ///         The following query shows including a single level of related entities.
    ///         <code>
    ///             context.Blogs.Include(blog =&gt; blog.Posts);
    ///         </code>
    ///     </para>
    ///     <para>
    ///         The following query shows including two levels of entities on the same branch.
    ///         <code>
    ///             context.Blogs
    ///                 .Include(blog =&gt; blog.Posts).ThenInclude(post =&gt; post.Tags);
    ///         </code>
    ///     </para>
    ///     <para>
    ///         The following query shows including multiple levels and branches of related data.
    ///         <code>
    ///             context.Blogs
    ///                 .Include(blog =&gt; blog.Posts).ThenInclude(post =&gt; post.Tags).ThenInclude(tag =&gt; tag.TagInfo)
    ///                 .Include(blog =&gt; blog.Contributors);
    ///         </code>
    ///     </para>
    ///     <para>
    ///         The following query shows including a single level of related entities on a derived type using casting.
    ///         <code>
    ///             context.Blogs.Include(blog =&gt; ((SpecialBlog)blog).SpecialPosts);
    ///         </code>
    ///     </para>
    ///     <para>
    ///         The following query shows including a single level of related entities on a derived type using 'as' operator.
    ///         <code>
    ///             context.Blogs.Include(blog =&gt; (blog as SpecialBlog).SpecialPosts);
    ///         </code>
    ///     </para>
    /// </example>
    /// <typeparam name="TEntity"> The type of entity being queried. </typeparam>
    /// <typeparam name="TProperty"> The type of the related entity to be included. </typeparam>
    /// <param name="source"> The source query. </param>
    /// <param name="navigationPropertyPath">
    ///     A lambda expression representing the navigation property to be included (<c>t =&gt; t.Property1</c>).
    /// </param>
    /// <returns>A new query with the related data included.</returns>
    public static IIncludableQueryable<TEntity, TProperty> Include<TEntity, TProperty>(
      this IQueryable<TEntity> source,
      Expression<Func<TEntity, TProperty>> navigationPropertyPath)
      where TEntity : class;

其中

/// <summary>
    ///     Specifies related entities to include in the query results. The navigation property to be included is specified starting with the
    ///     type of entity being queried (<typeparamref name="TEntity" />). If you wish to include additional types based on the navigation
    ///     properties of the type being included, then chain a call to
    ///     <see cref="M:Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ThenInclude``3(Microsoft.EntityFrameworkCore.Query.IIncludableQueryable{``0,System.Collections.Generic.IEnumerable{``1}},System.Linq.Expressions.Expression{System.Func{``1,``2}})" />
    ///     after this call.
    /// </summary>

这个方法适用于在查询结果中关联一些其他的实体。通过使用Linq中的属性来查看导航属性。如果还想关联另外的属性信息,需要使用ThenInclude。
几个应用举例:

 context.Blogs.Include(blog =>blog.Posts);
 context.Blogs.Include(blog => blog.Posts).ThenInclude(post=>post.Tags);
 context.Blogs.Include(blog => blog.Posts).ThenInclude(post => post.Tags).ThenInclude(tag =>tag.TagInfo)
 			  .Include(blog =>blog.Contributors);
路由数据

3.x与2.x的路由表示还是不一样的

2.X:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

3.X:

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }

其他

ValidateAntiForgeryToken 特性帮助抵御跨网站请求伪造 (CSRF) 攻击。 令牌通过 FormTagHelper 自动注入到视图中,并在用户提交表单时包含该令牌。 令牌由 ValidateAntiForgeryToken 特性验证。

模型绑定
[Microsoft.AspNetCore.Mvc.NonAction]
public virtual System.Threading.Tasks.Task<bool> TryUpdateModelAsync (object model, Type modelType, string prefix);

以基于已发布表单数据中的用户输入更新已检索实体中的字段。 Entity Framework 的自动更改跟踪在由表单输入更改的字段上设置 Modified 标记。 调用 SaveChanges 方法时,Entity Framework 会创建 SQL 语句,以更新数据库行。 忽略并发冲突,并且仅在数据库中更新由用户更新的表列。

if (await TryUpdateModelAsync<Student>(
        studentToUpdate,
        "",
        s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
    {
        try
        {
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        catch (DbUpdateException /* ex */)
        {
            //Log the error (uncomment ex variable name and write a log.)
            ModelState.AddModelError("", "Unable to save changes. " +
                "Try again, and if the problem persists, " +
                "see your system administrator.");
        }
    }
数据库连接关闭

数据库连接用完之后,需要进行关闭,释放数据库资源。ASP.NET Core内置依赖关系注入会完成此任务。
在依赖注入DbContext时默认的生存期是Scoped

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddDbContext<SchoolContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("defaultConnection")));
            services.AddMvc();
        }

查看解析生存期是ServiceLifetime.Scoped

 public static IServiceCollection AddDbContext<TContext>(
      this IServiceCollection serviceCollection,
      Action<DbContextOptionsBuilder> optionsAction = null,
      ServiceLifetime contextLifetime = ServiceLifetime.Scoped,
      ServiceLifetime optionsLifetime = ServiceLifetime.Scoped)
      where TContext : DbContext;

这说明上下文生存期与Web请求生存期一致,并在web请求结束时将自动调用Dispose方法。

数据库事务

默认情况EF会自动隐式实现事务。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值