Linux'ta .NET: Göründüğünden Daha Basit
Yayınlanan: 2022-08-16Linux üzerinde .NET çözümleri geliştirmek her zaman zor olmuştur çünkü Microsoft'un Visual Studio'su çalışmak için Windows'a ihtiyaç duyar. Birkaç .NET projesi üzerinde çalıştıktan sonra, Linux üzerinde .NET geliştirmenin sınırlarını test etmeye karar verdim. Bu basit öğretici, tercih ettiğim işletim sisteminde .NET geliştirmenin ne kadar zarif ve etkili olabileceğini göstermek için SQL Server ile bir ASP.NET MVC uygulamasına odaklanır.
Geliştirme Ortamı
İlk olarak, bizim özel Linux tarzımızla ilişkili .NET araçlarının ve SDK'nın Microsoft'un standart kılavuzu kullanılarak kurulduğundan emin olmalıyız.
Tercih ettiğim geliştirme ortamı, pencereli bir tümleşik geliştirme ortamından (IDE), güçlü bir veritabanı yönetimi ve sorgulama aracından, veritabanının kendisinden ve oluşturma ve dağıtım araçlarından oluşur. Sağlam işlevsellik elde etmek ve güzel bir kodlama deneyimi sağlamak için aşağıdaki araçları kullanıyorum:
- IDE: Visual Studio Kodu
- Veritabanı yönetimi ve sorgulama aracı: DBeaver
- Veritabanı: Microsoft SQL Server (Linux Kurulumu)
- Derleme araçları: .NET SDK Komut Satırı Arabirimi (CLI)
- Sanal makine ve konteynerler: Docker
Örnek uygulamamıza geçmeden önce bu araçların doğru şekilde kurulduğundan emin olun.
Proje İskelesi
Bu örnek uygulamada, varsayımsal bir ayakkabı mağazası envanter yönetim sistemi için bir dizi kullanım örneği aracılığıyla ASP.NET geliştirme ve işlevselliğini vurgulayacağız. Herhangi bir yeni .NET uygulamasında olduğu gibi, bir çözüm oluşturmamız ve ardından buna bir proje eklememiz gerekecek. Yeni çözümümüzün iskeletini oluşturmak için .NET SDK CLI araçlarından yararlanabiliriz:
mkdir Shoestore && cd Shoestore dotnet new sln
Ardından, basitlik adına açık bir ana sınıf içeren bir ASP.NET projesi oluşturun, çünkü bu proje yapısı ASP.NET geliştiricilerine en çok aşinadır. MVC desenini kullanarak projemizi oluşturalım:
mkdir Shoestore.mvc && cd Shoestore.mvc dotnet new mvc --use-program-main=true
Ardından, projeyi çözüme ekleyin:
# Go to the root of the solution cd .. dotnet sln add Shoestore.mvc/
Artık bir varsayılan çözümümüz ve içerdiği ASP.NET projesi var. Devam etmeden önce, her şeyin aşağıdakileri oluşturduğundan emin olun:
cd Shoestore.mvc/ dotnet restore dotnet build
İyi geliştirme uygulaması, daha iyi dağıtım ve taşınabilirlik için önemli hizmetleri ve uygulama çalışma zamanını Docker kapsayıcılarına yerleştirmeyi teşvik eder. Bu nedenle, uygulamamızı desteklemek için basit bir Docker kapsayıcı oluşturalım.
Uygulama Taşınabilirliği
Docker görüntüleri, işletim sistemi ve veritabanları dahil temel çözümler gibi temel gereksinimler için kabul edilen bir başlangıç noktası olarak genellikle başka bir ana Docker görüntüsüne başvurur. Bu Docker en iyi uygulamasını izleyerek, Microsoft tarafından yayınlanan üst görüntülere başvururken uygun hizmet yapılandırması için hem Dockerfile hem de Docker Compose dosyası oluşturun. İmajımızı küçük tutmak için Docker aşamalarını kullanacağız. Aşamalar, uygulamamızı oluştururken .NET SDK'yı kullanmamıza izin verir, böylece ASP.NET çalışma zamanının yalnızca uygulamamız çalışırken gerekli olur.
Aşağıdaki içeriklerle Shoestore.mvc
dosyasını oluşturun:
# Shoestore\Shoestore.mvc\Dockerfile # Build stage FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /shoestore COPY Shoestore.mvc/*.csproj ./ # Restore project packages RUN dotnet restore COPY Shoestore.mvc/* ./ # Create a release build RUN dotnet build -c Release -o /app/build # Run the application and make it available on port 80 FROM mcr.microsoft.com/dotnet/aspnet:6.0 WORKDIR /app EXPOSE 80 # Assets and views COPY Shoestore.mvc/Views ./Views COPY Shoestore.mvc/wwwroot ./wwwroot COPY --from=build /app/build ./ ENTRYPOINT [ "dotnet", "Shoestore.mvc.dll" ]
Ardından, çözümümüzün kök dizininde docker-compose.yml
dosyasını oluşturacağız. Başlangıçta, yalnızca uygulama hizmetimizin .Dockerfile
bir referans içerecektir:
# Shoestore/docker-compose.yml version: "3.9" services: web: build: context: . dockerfile: Shoestore.mvc/Dockerfile ports: - "8080:80"
Ayrıca, yalnızca derleme yapılarının görüntümüze kopyalandığından emin olmak için ortamımızı bir .dockerignore dosyasıyla yapılandıralım.
Uygulama hizmetimiz artık stubbed ve yürütme ortamı çalışmaya hazır olduğunda, veritabanı hizmetimizi oluşturmamız ve onu Docker yapılandırmamıza bağlamamız gerekiyor.
Veritabanı Hizmeti
Microsoft SQL Server'ı Docker yapılandırmamıza eklemek, özellikle Microsoft tarafından sağlanan bir Docker görüntüsünü değiştirmeden kullandığımız için basittir. Veritabanını yapılandırmak için docker-compose.yml
dosyasının altına aşağıdaki yapılandırma bloğunu ekleyin:
db: image: "mcr.microsoft.com/mssql/server" environment: SA_PASSWORD: "custom_password_123" ACCEPT_EULA: "Y" ports: - "1433:1433"
Burada ACCEPT_EULA
, kurulumun durmasını engeller ve ports
ayarımız, varsayılan SQL Server bağlantı noktasının çeviri olmadan geçmesine izin verir. Bununla, Oluştur dosyamız hem uygulama hizmetimizi hem de veritabanımızı içerir.
Uygulama kodunu özelleştirmeden önce Docker ortamımızın çalıştığını doğrulayalım:
# From the root of the solution docker compose up --build
Başlatma sırasında hiçbir hatanın görünmediğini varsayarsak, eksik örnek uygulamamız, http://localhost:8080
yerel adresindeki bir web tarayıcısı aracılığıyla erişilebilir olmalıdır.
Kod Oluşturma Araçları
Şimdi eğlenceli kısma odaklanıyoruz: uygulama kodunu özelleştirmek ve uygulama verilerinin Microsoft SQL Server veritabanında kalmasını sağlamak. Uygulamayı veritabanına bağlamak ve uygulamanın modelini, görünümünü, denetleyicisini ve EF için gerekli yapılandırmayı oluşturmak için hem Entity Framework (EF) hem de .NET SDK araçlarını kullanacağız.
İhtiyacımız olan araçları belirlemeden önce bir tool-manifest
dosyası oluşturmalıyız:
# From the root of the solution dotnet new tool-manifest
Bu basit komutlarla EF ve SDK araçlarını bu dosyaya ekleyin:
dotnet tool install dotnet-ef dotnet tool install dotnet-aspnet-codegenerator
Bu araçların doğru şekilde kurulduğunu doğrulamak için dotnet ef
çalıştırın. Bir tek boynuzlu at belirirse, doğru şekilde kurulmuşlardır. Ardından, ASP.NET araçlarını test etmek için dotnet aspnet-codegenerator
çalıştırın; çıktı, genel bir CLI kullanım bloğu olmalıdır.
Artık bu araçları kullanarak uygulamamızı oluşturabiliriz.
MVC: Modeli
Uygulamamızı oluştururken ilk görev model oluşturmaktır. Bu model daha sonra veritabanına ekleneceği için MS SQL Server ve EF paketlerini projemize dahil edeceğiz:
cd Shoestore.mvc/ dotnet add package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore dotnet add package Microsoft.EntityFrameworkCore.SqlServer dotnet add package Microsoft.EntityFrameworkCore.Tools dotnet restore
Ardından, veritabanına hangi modellerin ekleneceğini belirleyen ve kodumuzun bu verilere veritabanından kolayca erişmesini ve sorgulamasını sağlayan bir EF veritabanı bağlam nesnesi oluşturun.
EF'ye özel kodu barındırmak için bir Data
dizini oluşturun ve aşağıdaki içeriklerle Data/ApplicationDBContext.cs
dosyasını oluşturun:
// Shoestore/Shoestore.mvc/Data/ApplicationDBContext.cs using Microsoft.EntityFrameworkCore; namespace Shoestore.mvc.Data; public class ApplicationDBContext : DbContext { public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options):base(options){} }
Ardından, Dockerfile
yapılandırdığımız kimlik bilgileriyle eşleşmesi gereken veritabanı bağlantı dizesini yapılandırın. Shoestore/Shoestore.mvc/appsettings.json
içeriğini aşağıdaki gibi ayarlayın:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "Shoestore": "Server=db;Database=master;User=sa;Password=custom_password_123;" } }
Veritabanı bağlantı dizesi yapılandırılmış ve veritabanı bağlamı kodlanmış olarak, uygulamamızın Main
işlevini kodlamaya hazırız. Sistem hata ayıklamasını basitleştirmek için veritabanı istisnası işlemeyi dahil edeceğiz. Ek olarak, oluşturulan koddaki bir .NET hatası, Docker kapsayıcısının görünümlerimizi yanlış sunmasına neden olduğundan, görünüm hizmeti yapılandırmamıza belirli bir kod eklememiz gerekecek. Bu, Docker imajımızdaki dosya yollarını açıkça bizim konumumuza ayarlayacaktır:
using Microsoft.EntityFrameworkCore; using Shoestore.mvc.Data; namespace 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<ApplicationDBContext>( options => options.UseSqlServer(connectionString)); // Middleware to catch unhandled exceptions and display a stack trace builder.Services.AddDatabaseDeveloperPageExceptionFilter(); // Add services to the container. // ASP.NET has a known issue where the final built app doesn't know where the view // files are (in the Docker container). // The fix is to specifically add view locations. builder.Services .AddControllersWithViews() .AddRazorOptions(options => { options.ViewLocationFormats.Add("/{1}/{0}.cshtml"); options.ViewLocationFormats.Add("/Shared/{0}.cshtml"); });
Geliştirme modundayken sistemimize bir veritabanı geçiş bitiş noktası eklemek için aynı dosya içindeki IsDevelopment
if
ifadesine atlayın. Aşağıdaki kodla else
bir ifade ekleyin:
// Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { // Leave the contents of the if block alone. These are hidden for clarity. } else { app.UseMigrationsEndPoint(); }
Ardından, yeni paketlerin ve kaynak kodu düzenlemelerinin doğru şekilde derlendiğinden emin olmak için hızlı bir test yapın:
// Go to mvc directory cd Shoestore.mvc dotnet restore dotnet build
Şimdi Shoestore.mvc\Models\Shoe.cs
dosyasını oluşturarak modeli gerekli alanlarımızla dolduralım:
namespace Shoestore.mvc.Models; public class Shoe { public int ID { get; set; } public string? Name { get; set; } public int? Price { get; set; } public DateTime CreatedDate { get; set; } }
EF, ilişkili modele, bağlam dosyasına ve uygulamamızdaki herhangi bir EF koduna dayalı olarak SQL üretir. SQL sonuçları daha sonra çevrilir ve gerektiğinde kodumuza döndürülür. Shoe
modelimizi veritabanı bağlamımıza eklersek, EF, MS SQL Server ve uygulamamız arasında nasıl çeviri yapılacağını bilecektir. Bunu, Shoestore/Shoestore.mvc/Data/ApplicationDBContext.cs
veritabanı bağlam dosyasında yapalım:
using Microsoft.EntityFrameworkCore; using Shoestore.mvc.Models; namespace Shoestore.mvc.Data; public class ApplicationDBContext : DbContext { public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options) : base(options) { } private DbSet<Shoe>? _shoe { get; set; } public DbSet<Shoe> Shoe { set => _shoe = value; get => _shoe ?? throw new InvalidOperationException("Uninitialized property" + nameof(Shoe)); } }
Son olarak, modelimizi veritabanına almak için bir veritabanı geçiş dosyası kullanacağız. EF aracı, veritabanı bağlamına ve ilişkili modeline (yani, Shoe
) dayalı olarak MS SQL Server'a özgü bir geçiş dosyası oluşturur:
cd Shoestore.mvc/ dotnet ef migrations add InitialCreate
Bir denetleyicimiz olana ve yerinde görüntülenene kadar geçişimizi çalıştırmaya devam edelim.
MVC: Denetleyici ve Görünüm
ASP.NET kod oluşturma aracını kullanarak denetleyicimizi oluşturacağız. Bu araç çok güçlüdür ancak belirli yardımcı sınıflar gerektirir. Temel denetleyici yapısı ve EF entegrasyonu için Design
stili paketlerini kullanın. Bu paketleri ekleyelim:
cd Shoestore.mvc\ dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design && \ dotnet add package Microsoft.EntityFrameworkCore.Design && \ dotnet restore
Şimdi, varsayılan denetleyicimizi oluşturmak, aşağıdaki komutu çağırmak kadar basittir:
cd Shoestore.mvc\ dotnet dotnet-aspnet-codegenerator controller \ -name ShoesController \ -m Shoe \ -dc ApplicationDBContext \ --relativeFolderPath Controllers \ --useDefaultLayout \ --referenceScriptLibraries
Kod oluşturucu denetleyicimizi oluşturduğunda, o denetleyici için basit bir görünüm de oluşturur. MVC temellerimiz tamamlandığında, her şeyi çalıştırmaya hazırız.
Taşıma ve Uygulama Testi
EF geçişleri genellikle basit bir meseledir, ancak Docker söz konusu olduğunda süreç daha karmaşık hale gelir. Dizimizin bir sonraki makalesinde, bu geçişleri Docker çözümümüzde çalıştırmanın harika dolambaçlı yolunu keşfedeceğiz, ancak şimdilik sadece geçişimizin çalışmasını istiyoruz.
Tüm yapılandırma ve taşıma dosyaları depomuza dahil edilmiştir. Tüm projeyi yerel makinemize klonlayalım ve geçişi gerçekleştirelim:
git clone https://github.com/theZetrax/dot-net-on-linux.git cd ./dot-net-on-linux docker composer up
docker composer
oluşturucu işlemi uygulamamızı oluşturur, geçişi çalıştırır ve .NET çalışma zamanı ile ASP.NET uygulamamızı başlatır. Çalışan çözüme erişmek için http://localhost:8080/Shoes
adresini ziyaret edin.
Uygulama arayüzümüz basit olmasına rağmen, görünümden veritabanına kadar tüm katmanlarda işlevsellik gösterir.
Linux'ta .NET Sadece Çalışıyor
Çözümümüze genel bir bakış için tam depoya bakın. Sonraki makale, Docker görüntülerimizi yalın hale getirmek için ipuçları ve püf noktalarının yanı sıra geçişimizi ayrıntılı olarak ele alacaktır.
Linux'ta .NET boş bir hayalden daha fazlasıdır: Uygulanabilir bir dil, çalışma zamanı ve işletim sistemi birleşimidir. Visual Studio'da yetiştirilen birçok geliştirici, .NET CLI'yi sonuna kadar kullanma deneyimine sahip olmayabilir, ancak bu araçlar etkili ve güçlüdür.
Toptal Mühendislik Blogunda Daha Fazla Okuma:
- ASP.NET Core ile ASP.NET Web API'si Oluşturma
- Microsoft Stack'in Hala Geçerli Bir Seçim Olmasının 8 Nedeni
- Önbelleğe Alma ile Web Çiftliğinde ASP.NET Uygulama Performansı Nasıl İyileştirilir
- .NET Geliştiricileri için Elasticsearch Eğitimi
- Kubernetes Nedir? Konteynerleştirme ve Dağıtım Kılavuzu
Toptal Engineering Blog, bu makalede sunulan kod örneklerini gözden geçirdiği için Henok Tsegaye'ye şükranlarını sunar.