authors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.
Zablon Dawit
Verified Expert in Engineering
5 Years of Experience

Zablon是一个专注于ASP的全栈web开发人员.。NET和JavaScript. He has created enterprise software for various companies, including Pelmorex Corp and S.R.E软件开发.

Share

Developing .NET solutions on Linux has always been challenging because Microsoft’s Visual Studio requires Windows in order to work. 在研究了几个 .NET 项目中,我决定测试一下开发的极限 .NET on Linux. 这个简单的教程主要介绍一个 ASP.NET MVC 应用程序与SQL Server显示如何优雅和有效 .NET development 能在我喜欢的操作系统上运行吗.

开发环境

首先,我们必须确保 .. NET工具和SDK与 Linux的特殊风格 安装时使用 微软的标准指南.

My preferred development environment consists of a windowed integrated development environment (IDE), 一个强大的数据库管理和查询工具, 数据库本身, 以及用于构建和部署的工具. I use the following tools to achieve solid functionality and enable a beautiful coding experience:

Make sure these tools are properly installed before you proceed with our sample application.

项目脚手架

在这个示例应用程序中,我们将突出显示ASP.NET development and functionality through a series of use cases for a hypothetical shoe store inventory management system. As with any new .NET application, we’ll need to create a solution and then add a project to it. 我们可以利用 .. NET SDK CLI工具来支撑我们的新解决方案:

mkdir Shoestore && cd Shoestore
dotnet new sln

Next, create an ASP.NET 为简单起见,包含显式主类的项目, 由于这个项目的结构是最熟悉的 ASP.NET developers. 控件创建项目 MVC pattern:

mkdir Shoestore.mvc && cd Shoestore.mvc
Dotnet新MVC——use-program-main=true

接下来,将项目添加到解决方案中:

#找到解决方案的根源
cd ..
. net添加鞋店.mvc/

我们现在有了一个默认的解决方案,它包含了ASP.NET project. 在继续之前,确保一切都构建好了:

cd Shoestore.mvc/
dotnet restore
dotnet build

良好的开发实践 encourages putting key services and the application runtime into Docker containers for improved deployment and portability. Therefore, let’s create a simple Docker container to support our application.

应用程序的可移植性

Docker images typically reference another parent Docker image as an accepted starting point for essential requirements like OS and basic solutions, 包括数据库. 按照这个Docker最佳实践,创建一个 Dockerfile and a Docker Compose file for proper service configuration while referencing Microsoft-published parent images. We’ll use Docker stages 让我们的形象保持小一点. 阶段允许我们使用 .. NET SDK在构建我们的应用程序时使用.只有在应用程序运行时才需要。NET运行时.

Create the Shoestore.mvc Dockerfile,内容如下:

# Shoestore \ Shoestore.mvc\Dockerfile
# Build stage
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR / shoestore
COPY Shoestore.mvc/*.csproj ./
#恢复项目包
运行dotnet恢复
COPY Shoestore.mvc/* ./
创建一个发布版本
运行dotnet build -c Release -o /app/build

#运行应用程序并使其在端口80上可用
FROM mcr.microsoft.com/dotnet/aspnet: 6.0
WORKDIR /app
EXPOSE 80
#资产和视图
COPY Shoestore.mvc/Views ./Views
COPY Shoestore.mvc/wwwroot ./wwwroot
COPY——from=build /app/build ./
入口点["。net", "Shoestore ".mvc.dll" ]

接下来,我们将创建 docker-compose.yml 文件在我们的解决方案的根目录. 最初,它将只包含对应用程序服务的引用 .Dockerfile:

# Shoestore / docker-compose.yml
version: "3.9"
services:
  web:
    build:
      context: .
      dockerfile: Shoestore.mvc/Dockerfile
    ports:
      - "8080:80"

我们还可以用 .dockerignore文件 确保只有构建工件被复制到我们的映像中.

With our application service now stubbed in and its execution environment ready to run, we need to create our database service and connect it to our Docker configuration.

数据库服务

Adding the Microsoft SQL Server to our Docker configuration is straightforward, especially since we are using a Microsoft-provided Docker image without changing it. 的底部添加以下配置块 docker-compose.yml 配置数据库的文件:

  db:
    image: "mcr.microsoft.com/mssql/server”
    environment:
      SA_PASSWORD:“custom_password_123”
      ACCEPT_EULA: "Y"
    ports:
      - "1433:1433"

Here, ACCEPT_EULA 防止安装停止,我们的 ports setting lets the default SQL Server port pass through without translation. With that, our Compose file includes both our application service and database.

Before customizing the application code, let’s verify that our Docker environment works:

#从解决方案的根开始
Docker compose up——build

假设启动过程中没有出现错误, our incomplete sample application should be available through a web browser at the local address http://localhost:8080.

代码生成工具

Now we get to focus on the fun part: customizing the application code and ensuring that the application data persists in the Microsoft SQL Server database. 我们将同时使用 Entity Framework (EF) and .NET SDK tools to connect the application to the database and scaffold the application’s model, view, controller, 和ef要求的配置.

在指定所需的工具之前,必须创建一个 tool-manifest file:

#从解决方案的根开始

Dotnet新工具清单

使用以下简单命令将EF和SDK工具添加到该文件中:

Dotnet工具安装Dotnet -ef
Dotnet工具安装Dotnet -aspnet-codegenerator

要验证这些工具的正确安装,请运行 dotnet ef. 如果出现独角兽,说明安装正确. Next, run dotnet aspnet-codegenerator to test the ASP.NET tools; the output should be a general CLI usage block.

现在我们可以使用这些工具来创建应用程序.

MVC: Model

构建应用程序的第一个任务是创建模型. 因为这个模型稍后会添加到数据库中, 我们将在我们的项目中包含MS SQL Server和EF包:

cd Shoestore.mvc/
dotnet添加软件包微软.AspNetCore.Diagnostics.EntityFrameworkCore
dotnet添加软件包微软.EntityFrameworkCore.SqlServer
dotnet添加软件包微软.EntityFrameworkCore.Tools
dotnet restore

Next, create an EF database context object that determines which models are added to the database, and allows our code to easily access and query that data from the database.

Create a Data 目录来存放特定于ef的代码,并创建 ApplicationDBContext.cs 包含以下内容的文件:

/ / Shoestore / Shoestore.mvc /数据/ ApplicationDBContext.cs
using Microsoft.EntityFrameworkCore;

名称空间Shoestore.mvc.Data;

ApplicationDBContext: DbContext
{
  public ApplicationDBContext(DbContextOptions options):base(options){}
}

Next, 配置数据库连接字符串, 哪个必须与我们配置的凭据相匹配 Dockerfile. 的内容 Shoestore / Shoestore.mvc/appsettings.json 致:

{
  "Logging": {
    "LogLevel": {
      “默认”:“信息”,
      "Microsoft.AspNetCore”:“警告”
    }
  },
  “AllowedHosts”:“*”,
  " ConnectionStrings ": {
    "Shoestore": "Server=db;Database=master;User=sa;Password=custom_password_123;"
  }
}

配置了数据库连接字符串并对数据库上下文进行了编码, 我们已经准备好编写应用程序了 Main function. We’ll include 数据库异常处理 简化系统调试. 另外,因为a .NET bug in the generated code causes the Docker container to serve our views incorrectly, 我们需要在视图服务配置中添加特定的代码. This will explicitly set the file paths to our view location in our Docker image:

using Microsoft.EntityFrameworkCore;
using Shoestore.mvc.Data;

名称空间Shoestore.mvc;

// ...

    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder (args);
        // Associate our EF database context and configure it with our connection string
        var connectionString = builder.Configuration.GetConnectionString(“Shoestore”);
        builder.Services.AddDbContext(
            options => options.UseSqlServer (connectionString));
        //中间件捕获未处理的异常并显示堆栈跟踪
        builder.Services.AddDatabaseDeveloperPageExceptionFilter ();

        //向容器中添加服务.
        // ASP.NET has a known issue where the final built app doesn't know where the view
        //文件(在Docker容器中). 
        //修复方法是专门添加视图位置.
        builder.Services
            .AddControllersWithViews ()
            .AddRazorOptions(options => {
                options.ViewLocationFormats.Add("/{1}/{0}.cshtml");
                options.ViewLocationFormats.Add("/Shared/{0}.cshtml");
            });

Skip down to the IsDevelopment if statement within the same file to add a database migration endpoint to our system when it is in development mode. Add an else 语句,代码如下:

        //配置HTTP请求管道.
        if (!app.Environment.IsDevelopment())
        {
            //保留if块的内容. 为了清晰起见,这些都隐藏起来了.
        } else {
            app.UseMigrationsEndPoint ();
        }

Next, run a quick test to ensure the new packages and the source code edits compile correctly:

//进入mvc目录
cd Shoestore.mvc
dotnet restore
dotnet build

现在,让我们用必需的字段填充模型 Shoestore.mvc\Models\Shoe.cs file:

名称空间Shoestore.mvc.Models;

鞋的公共类
    public int ID { get; set; }
    public string? Name { get; set; }
    public int? Price { get; set; }
    public DateTime CreatedDate { get; set; }
}

EF generates SQL based on the associated model, its context file, and any EF code in our application. 然后根据需要将SQL结果翻译并返回到我们的代码中. If we add our Shoe 模型到我们的数据库上下文, EF将知道如何在MS SQL Server和我们的应用程序之间进行转换. 让我们在数据库上下文文件中做这个, Shoestore / Shoestore.mvc /数据/ ApplicationDBContext.cs:

using Microsoft.EntityFrameworkCore;
using Shoestore.mvc.Models;

名称空间Shoestore.mvc.Data;

ApplicationDBContext: DbContext
{
  public ApplicationDBContext(DbContextOptions options) : base(options) { }

    private DbSet? _shoe { get; set; }
    public DbSet Shoe {
        set => _shoe = value;
        get => _shoe ?? throw new InvalidOperationException("Uninitialized property" + nameof(Shoe));
    }
}

Finally, we’ll use a database migration file to get our model into the database. The EF tool creates a migration file specific to MS SQL Server based on the database context and its associated model (i.e., Shoe):

cd Shoestore.mvc/
dotnetef migrations添加InitialCreate

Let’s hold off on running our migration until we have a controller and view in place.

MVC:控制器和视图

我们将使用ASP创建我们的控制器.. NET代码生成工具. 这个工具非常强大,但需要特定的助手类. Use the Design 风格包的基本控制器结构及其EF集成. 让我们添加这些包:

cd Shoestore.mvc\
dotnet添加软件包微软.VisualStudio.Web.CodeGeneration.Design && \
dotnet添加软件包微软.EntityFrameworkCore.Design && \
dotnet restore

Now, creating our default controller is as simple as invoking the following command:

cd Shoestore.mvc\
代码生成器控制器
        -name ShoesController
        -m Shoe \
        -dc ApplicationDBContext
        ——relativeFolderPath Controllers \
        ——useDefaultLayout \
        ——referenceScriptLibraries

When the code generator creates our controller, it also creates a simple view for that controller. 完成MVC基础之后,我们就可以让一切运行起来了.

迁移和应用测试

EF迁移通常是一件简单的事情, 但一旦牵涉到Docker, 这个过程变得更加复杂. 在我们系列的下一篇文章中, we’ll explore the wonderfully twisty path to making those migrations work in our Docker solution,但是现在,我们只想运行迁移.

所有配置和迁移文件都包含在我们的存储库中. Let’s clone the full project to our local machine and perform the migration:

Git克隆http://github.com/theZetrax/dot-net-on-linux.git
cd ./ dot-net-on-linux
Docker composer up

The docker composer operation builds our application, runs the migration, and launches our ASP.. NET应用程序 .NET runtime. 要访问运行解决方案,请访问 http://localhost:8080/Shoes.

尽管我们的应用程序接口很简单, 它演示了所有层的功能, 从视图到数据库.

.. NET在Linux上工作

See the full repository 查看我们解决方案的概述. 下一篇文章将详细介绍我们的迁移, 以及使Docker镜像精简的技巧和技巧.

.NET on Linux is more than just a pipe dream: It’s a viable language, runtime, and OS combination. Many 在Visual Studio中成长起来的开发者 可能没有使用经验 .NET CLI,但这些工具是有效和强大的.

Toptal Engineering博客向 Henok Tsegaye 查看本文中提供的代码示例.

了解基本知识

  • What is .NET Core CLI?

    .. NET Core CLI,现在称为 .. NET CLI,包括可用于任何命令行接口 .NET-supported平台. We use these tools for project creation, scaffolding, building, and ancillary execution.

  • Can you build a .. NET框架?

    是的,发展 .. NET在Linux上得到很好的支持.

  • Is .NET Core在Linux上很好?

    .. NET (Core)在Linux上是强大的. Both the development tools and runtime are robust enough for production use.

聘请Toptal这方面的专家.
Hire Now
Zablon Dawit

Zablon Dawit

Verified Expert in Engineering
5 Years of Experience

亚的斯亚贝巴,埃塞俄比亚

自2021年12月15日起成为会员

About the author

Zablon是一个专注于ASP的全栈web开发人员.。NET和JavaScript. He has created enterprise software for various companies, including Pelmorex Corp and S.R.E软件开发.

authors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.

世界级的文章,每周发一次.

输入您的电子邮件,即表示您同意我们的 privacy policy.

世界级的文章,每周发一次.

输入您的电子邮件,即表示您同意我们的 privacy policy.

Toptal开发者

Join the Toptal® community.