EF Core'da connection string (bağlantı dizesi) koda yazılmaz; ASP.NET Core ve generic host kullanan uygulamalarda yapılandırma sisteminde saklanır ve Program.cs içinde builder.Configuration.GetConnectionString("Ad") ile okunup UseSqlServer, UseSqlite gibi sağlayıcı metotlarına verilir. Geliştirme ortamında parola gibi gizli bilgiler için Secret Manager (dotnet user-secrets), üretimde ise ortam değişkenleri veya Azure Key Vault gibi güvenli kaynaklar kullanılır. Resmî belgelerin kuralı açıktır: gizli bilgiler yapılandırma dosyalarına eklenmemelidir.
Bu yazı, Entity Framework Core (EF Core) belgelerindeki connection string sayfasını ve onu tamamlayan migration, scaffolding ve interceptor sayfalarını bir araya getiriyor: bağlantı dizesinin neden ayrıca korunması gerektiği, appsettings ve user secrets kullanımı, scaffolding'deki Name= sözdizimi, WinForms ve WPF'deki klasik yöntem, EF araçlarının tasarım zamanında hangi bağlantıyı kullandığı, üretimde migration uygularken bağlantının nasıl verileceği ve EF Core 10'da SQL Server bağlantı dizelerini etkileyen bir değişiklik.
Bağlantı dizesi neden ayrıca yönetilmeli?
Belgeler bağlantı dizelerinin iki özelliğini öne çıkarır. Birincisi, korunması gereken hassas bilgiler içerebilirler: sunucu adresi, kullanıcı adı ve parola. İkincisi, uygulama geliştirme, test ve üretim gibi farklı ortamlara geçtikçe değişmeleri gerekebilir. Bu iki özellik birlikte düşünüldüğünde, bağlantı dizesini kaynak koda gömmek iki sorunu birden yaratır: parola kaynak kontrolüne girer ve her ortam için kodu değiştirmeniz gerekir.
Resmî başlangıç öğreticisi bile bağlantı dizesini koda yazdıktan sonra, üretim uygulamalarında bağlantı dizelerinin kodda saklanmaması gerektiğini ayrıca not eder. EF Core'un genel bakış sayfası da üretim için güvenlik incelemesi önerirken ilk örnek olarak bağlantı dizelerinin ve diğer gizli bilgilerin ele alınışını sayar. Kendi sunucunuzda çalışan bir uygulama için bu, depoda (repository) hiçbir zaman gerçek bir üretim parolasının bulunmaması demektir.
ASP.NET Core yapılandırmasında bağlantı dizesi

ASP.NET Core yapılandırması bağlantı dizelerini farklı sağlayıcılarda saklayabilir. Belgeler dört seçenek sayar:
appsettings.Development.jsonveyaappsettings.jsondosyası,- bir ortam değişkeni,
- Azure Key Vault,
- Secret Manager aracı.
Parolasız bir geliştirme bağlantısı (örneğin Windows kimlik doğrulamasıyla LocalDB) ya da yalnızca dosya adı içeren bir SQLite bağlantısı yapılandırma dosyasında durabilir. Belgelerdeki örnek appsettings.json şöyledir:
{
"ConnectionStrings": {
"BloggingDatabase": "Server=(localdb)\\mssqllocaldb;Database=EFGetStarted.ConsoleApp.NewDb;Trusted_Connection=True;"
}
}Dikkat edilmesi gereken küçük ama sık yapılan bir hata: JSON içinde ters bölü karakteri kaçış karakteridir, bu yüzden (localdb)\mssqllocaldb değeri dosyada iki ters bölü ile yazılır. C# kodundaki @"..." dizelerinde ise tek ters bölü yeterlidir.
Context genellikle Program.cs içinde, bağlantı dizesi yapılandırmadan okunarak yapılandırılır. GetConnectionString metodu, anahtarı ConnectionStrings:<bağlantı dizesi adı> olan yapılandırma değerini arar ve Microsoft.Extensions.Configuration ad alanını gerektirir. Belgedeki örnek, değer bulunamazsa uygulamanın sessizce yanlış bir bağlantıyla devam etmesi yerine açık bir hata vermesini sağlar:
var conString = builder.Configuration.GetConnectionString("BloggingContext") ??
throw new InvalidOperationException("Connection string 'BloggingContext'" +
" not found.");
builder.Services.AddDbContext<BloggingContext>(options =>
options.UseSqlServer(conString));Buradaki ?? ve throw kalıbı bilinçli bir tercihtir: yapılandırmada bir yazım hatası ya da eksik bir ortam değişkeni varsa uygulama başlarken, hatanın nedenini söyleyen bir mesajla durur. Context'in AddDbContext ile kaydı ve yaşam süresi DbContext yapılandırma ve yaşam döngüsü yazısında ayrıntılı anlatılıyor.
Geliştirmede Secret Manager (user secrets)
Geliştirme makinenizde parola içeren bir bağlantı dizesi gerekiyorsa, belgelerin örnek olarak gösterdiği araç Secret Manager'dır: veritabanı parolasını yapılandırma dosyalarınıza yazmadan saklamanızı sağlar. Aracın kendisi ASP.NET Core belgelerinde ayrıntılı anlatılır; EF Core belgeleri onu bağlantı dizeleriyle nasıl kullanacağınızı gösterir. Önce proje için user secrets başlatılır, ardından bağlantı dizesi ConnectionStrings: önekiyle kaydedilir:
dotnet user-secrets init
dotnet user-secrets set ConnectionStrings:YourDatabaseAlias "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=YourDatabase"Kaydedilen değer yapılandırma sistemine eklenir ve GetConnectionString("YourDatabaseAlias") ile okunabilir. Belgeler, örneğin yerelde bir Docker container'ında çalışan SQL Server'a bağlanmak için LocalDB yerine kullanıcı adı ve parolayla SQL kimlik doğrulaması kullanan bir örnek de verir:
dotnet user-secrets set ConnectionStrings:YourDatabaseAlias "Server=localhost,1433;Database=YourDatabase;User Id=<username>;Password=<password>;TrustServerCertificate=True"Secret Manager bir geliştirme aracıdır; üretim sunucunuzda bu değerleri ortam değişkenleri ya da Azure Key Vault gibi bir kaynaktan sağlarsınız. ASP.NET Core yapılandırma sisteminin ayrıntıları (hangi kaynağın hangisini ezdiği gibi) ASP.NET Core belgelerinin konusudur; EF Core açısından önemli olan, context'in bağlantı dizesini kaynağı ne olursa olsun yapılandırmadan okumasıdır.
Scaffolding'de Name= sözdizimi
Var olan bir veritabanından model üretirken (scaffolding) bağlantı dizesini komut satırına açıkça yazmak, onun hem komut geçmişinde hem de üretilen kodda kalmasına yol açabilir. Belgelere göre bağlantı dizesini Secret Manager'da sakladığınızda scaffolding komutuna Name=<veritabanı takma adı> biçiminde bir bağlantı dizesi verirsiniz; araç değeri projenin yapılandırma kaynaklarından okur:
dotnet ef dbcontext scaffold Name=ConnectionStrings:YourDatabaseAlias Microsoft.EntityFrameworkCore.SqlServerVisual Studio Package Manager Console'da karşılığı Scaffold-DbContext 'Name=ConnectionStrings:YourDatabaseAlias' Microsoft.EntityFrameworkCore.SqlServer komutudur. Bu yöntemin ek bir faydası daha var: scaffolding, bağlantı dizesini açıkça verdiğinizde onu üretilen OnConfiguring metoduna koyar ve üstüne bir uyarı ekler. Belgelerdeki örnek çıktı şöyledir:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
=> optionsBuilder.UseSqlServer("Data Source=(LocalDb)\\MSSQLLocalDB;Database=AllTogetherNow");Belgeler bunun, üretilen kodun ilk kullanımda çökmemesi için yapıldığını, ama uyarının da söylediği gibi bağlantı dizelerinin üretim kodunda bulunmaması gerektiğini açıklar. Context'i zaten AddDbContext ile yapılandıracaksanız --no-onconfiguring (PMC'de -NoOnConfiguring) seçeneğiyle OnConfiguring metodunun hiç üretilmemesini sağlayabilirsiniz. Komut satırında bağlantı dizesini açıkça yazmanız gerekirse tırnak ve kaçış kurallarının kullandığınız kabuğa bağlı olduğunu unutmayın; belgelerin örneğine göre PowerShell $ karakterinin kaçışını gerektirir, ters bölüyü gerektirmez. Scaffolding'in tüm seçenekleri scaffold-dbcontext ile database first yazısında.
WinForms, WPF ve UWP uygulamaları
ASP.NET Core dışındaki masaüstü uygulamaları için belgeler, WinForms, WPF ve ASP.NET 4 uygulamalarının denenmiş klasik yöntemini anlatır: bağlantı dizesi uygulamanın App.config dosyasına (ASP.NET'te Web.config) eklenir. Kullanıcı adı ve parola gibi hassas bilgi içeren bağlantı dizelerinde yapılandırma dosyasının içeriği Protected Configuration ile korunmalıdır.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="BloggingDatabase"
connectionString="Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;" />
</connectionStrings>
</configuration>EF Core bağlantı dizelerinde providerName ayarı gerekmez, çünkü sağlayıcı kodda yapılandırılır. Değer, context'in OnConfiguring metodunda ConfigurationManager API'siyle okunur; bunun için System.Configuration framework derlemesine referans eklemeniz gerekebilir:
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(ConfigurationManager.ConnectionStrings["BloggingDatabase"].ConnectionString);
}
}UWP uygulamaları için belgeler farklı bir değerlendirme yapar: bu uygulamalardaki bağlantı dizesi genellikle yalnızca yerel bir dosya adını belirten bir SQLite bağlantısıdır, hassas bilgi içermez ve uygulama dağıtılırken değişmesi gerekmez. Bu yüzden kodda bırakılması genellikle sorun değildir (örneğin optionsBuilder.UseSqlite("Data Source=blogging.db")). Aynı mantık, sunucu tarafında yalnızca dosya adı içeren SQLite bağlantıları için de bir ölçüt sunar: içinde gizli bilgi yoksa sorun güvenlik değil, ortamlara göre değişip değişmeyeceğidir.
EF araçları hangi bağlantı dizesini kullanır?
dotnet ef migrations add, database update gibi komutlar context'i oluşturmak için uygulama kodunuzu çalıştırır. Bu yüzden sağlayıcı seçimi, bağlantı dizesi ve model yapılandırması uygulamanın ortamına bağlı olabilir. Belgelere göre EF Core tasarım zamanı araçları, ne ASPNETCORE_ENVIRONMENT ne de DOTNET_ENVIRONMENT ayarlıysa Development ortamını kullanır. Yani yerelde database update çalıştırdığınızda, aksini belirtmedikçe geliştirme yapılandırmasındaki bağlantı dizesi kullanılır.
Hedef veritabanını komut bazında değiştirmenin iki yolu vardır. Birincisi ortamı açıkça belirtmektir; belgelere göre ASP.NET Core projelerinde -- işaretinden sonraki argümanlar uygulamaya iletilir. İkincisi, bağlantı dizesini doğrudan vermektir: database update ve migrations list komutlarının --connection seçeneği, varsayılan olarak AddDbContext veya OnConfiguring içinde belirtilen bağlantının yerine geçer.
dotnet ef database update -- --environment Production
dotnet ef database update --connection "<bağlantı dizesi>"Bu komutların ve tasarım zamanında context'in nasıl oluşturulduğunun ayrıntıları dotnet ef komutları ve design-time DbContext factory yazılarında.
Üretimde migration uygularken bağlantı

Migration'ları üretim veritabanına uygularken bağlantı dizesi en çok sızdırılan yerlerden birine dönüşebilir. Belgelerin "Applying Migrations" sayfası bu konuda net kurallar koyar:
- Kaynak kontrolüne ve pakete koymayın: Üretim bağlantı dizelerini kaynak kontrolünde saklamayın ve migration bundle'ın içine gömmeyin. Dağıtım bağlantısını dağıtım sisteminin gizli bilgi deposundan sağlayın.
- Yetkileri ayırın: Dağıtımı yapan kimliğin şema değiştirme yetkileri olmalıdır; uygulamanın normal çalışırken kullandığı kimliğin genellikle olmamalıdır.
- Ortamı açıkça ayarlayın: Dağıtım çıktısını üretirken ve bundle'ı çalıştırırken ortamı açıkça belirtin. Belgelere göre bu, bir bundle'ın beklenmedik biçimde geliştirme user secrets değerlerini yüklemesini de önler.
- Ayar dosyalarına dikkat: Context yapılandırmanız
appsettings.jsonokuyorsa gerekli ayar dosyalarını bundle'ın yanına kopyalamanız gerekir; dosyalar bundle'ın çalıştığı klasörden okunur. Bu dosyalara üretim gizli bilgilerini koymayın; onları güvenli bir yapılandırma kaynağından ya da--connectionseçeneğiyle verin.
Belgeler bunu POSIX uyumlu bir kabukta şöyle gösterir; bağlantı dizesi bir ortam değişkeninden gelir ve komut satırına düz metin olarak yazılmaz:
ASPNETCORE_ENVIRONMENT=Production \
dotnet ef migrations bundle --output artifacts/efbundle
ASPNETCORE_ENVIRONMENT=Production \
./efbundle --connection "$DEPLOYMENT_CONNECTION_STRING"Bundle, SQL script ve çalışma zamanında uygulama seçeneklerinin karşılaştırması migration'ları production'a uygulama yazısında. Migration öncesinde veritabanı yedeği almayı da unutmayın; yedekleme yaklaşımları için veritabanı yedekleme stratejileri yazısına bakabilirsiniz.
Kiracıya göre değişen bağlantı: interceptor ile geç başlatma
Bağlantı dizeleri genellikle bir yapılandırma dosyasından okunan sabit değerlerdir. Ancak belgelerin belirttiği gibi bazen her context örneği için değişebilir; örneğin çok kiracılı bir sistemde her kiracının ayrı bir veritabanı olabilir. Belgelerdeki interceptor örneği bu durumda context'i hiç bağlantı dizesi vermeden yapılandırır:
services.AddDbContext<CustomerContext>(
b => b.UseSqlServer());Ardından bir DbConnectionInterceptor, bağlantı ilk kez açılmadan hemen önce (ConnectionOpeningAsync içinde) kiracıya ait bağlantı dizesini asenkron olarak bulup bağlantıya atar. Belgelere göre bağlantı dizesi yalnızca bağlantının ilk kullanımında alınır; sonrasında DbConnection üzerinde saklanan değer kullanılır. Örnekteki interceptor, bağlantı dizesini veren servis yalnızca asenkron çağrılabildiği için senkron ConnectionOpening metodunda bilinçli olarak hata fırlatır. Belgeler ayrıca her ihtiyaçta bağlantı dizesi veya erişim token'ı için asenkron sorgu yapmanın çok yavaş olabileceği, bu değerleri önbelleğe alıp yalnızca belirli aralıklarla yenilemeyi düşünmeniz gerektiği konusunda uyarır. Interceptor'ların genel kullanımı SQL loglama: LogTo ve interceptor yazısında, kiracı başına veritabanı ve context yaşam süresi seçimi ise global query filter ve multitenancy yazısında anlatılıyor.
Bağlantı havuzu ayarları nerede yapılır?
EF Core bağlantı havuzunu kendisi uygulamaz; belgelere göre bu iş alt seviyedeki veritabanı sürücüsüne (örneğin ADO.NET sürücüsüne) bırakılır. Havuz genellikle varsayılan olarak açıktır ve her türlü havuz yapılandırması sürücü düzeyinde, o sürücünün belgelediği şekilde yapılır. ADO.NET kullanırken en küçük ve en büyük havuz boyutu gibi parametreler genellikle bağlantı dizesi üzerinden ayarlanır. Bu, EF Core'un context havuzundan (AddDbContextPool) tamamen bağımsız bir mekanizmadır; ikisinin farkı DbContext pooling yazısında anlatılıyor. SQL Server sağlayıcısı alt katmanda Microsoft.Data.SqlClient kullanır; kabul edilen bağlantı dizesi anahtarları için SqlClient belgelerine bakmanız gerekir.
EF Core 10: SQL Server bağlantı dizesine Application Name ekleniyor
EF Core 10'un kırıcı değişiklikler listesinde bağlantı dizelerini doğrudan etkileyen bir madde var. SQL Server sağlayıcısına Application Name içermeyen bir bağlantı dizesi verildiğinde EF artık bu değeri kendisi ekler; eklenen değer, kullanılan EF ve SqlClient sürümleri hakkında anonim bilgi içerir. Belgelere göre bu çoğu durumda uygulamayı hiç etkilemez, ama bazı uç durumlarda davranışı değiştirebilir.
Belgelerdeki örnek şudur: aynı veritabanına hem EF ile hem de EF dışı bir teknolojiyle (Dapper, ADO.NET) bağlanıyorsanız, EF artık güncellenmiş, farklı bir bağlantı dizesi kullandığı için SqlClient iki ayrı iç bağlantı havuzu kullanır. Bu karma erişim bir TransactionScope içinde yapılıyorsa, SqlClient iki bağlantı dizesini iki ayrı veritabanı gibi gördüğü için daha önce gerekmeyen bir dağıtık transaction'a yükselmeye yol açabilir. Çözüm basittir: bağlantı dizenizde kendiniz bir Application Name tanımlayın. Tanımlı olduğunda EF onu ezmez ve bağlantı dizesi olduğu gibi korunur. Transaction davranışının ayrıntıları için transaction yönetimi yazısına bakabilirsiniz.
Sık yapılan hatalar

- Parolayı appsettings.json'a yazmak: Belgelere göre gizli bilgiler yapılandırma dosyalarına eklenmemelidir; geliştirmede Secret Manager, üretimde ortam değişkeni veya Key Vault gibi bir kaynak kullanın.
- Yanlış ortamda migration uygulamak: Araçlar ortam belirtilmezse
Developmentkullanır. Üretime uygulama yaparken ortamı ya da bağlantıyı açıkça verin. - TrustServerCertificate=True ayarını üretime taşımak: Bu ayar sertifika doğrulamasını atlar ve yalnızca yerel geliştirme içindir.
- Scaffold edilen OnConfiguring'i olduğu gibi bırakmak: Üretilen koddaki bağlantı dizesini kaldırın;
Name=sözdizimini veya--no-onconfiguringseçeneğini kullanın. - JSON kaçışını unutmak: appsettings içinde ters bölü iki kez yazılır.
- Eksik bağlantı dizesini kontrol etmemek: Belgelerdeki örnek,
GetConnectionStringsonucunu??ile kontrol edip değer yoksa açık birInvalidOperationExceptionfırlatır; bu kalıp, eksik yapılandırmayı uygulama başlarken görünür kılar. - Dağıtım ve uygulama kimliğini aynı tutmak: Şema değiştirme yetkisi yalnızca migration'ı uygulayan dağıtım kimliğinde olmalıdır.
Sık Sorulan Sorular
Bağlantı dizesini nereye yazmalıyım?
ASP.NET Core veya generic host kullanan uygulamalarda yapılandırma sistemine: hassas bilgi içermeyen geliştirme değerleri appsettings.Development.json dosyasına, parola içeren geliştirme değerleri Secret Manager'a, üretim değerleri ise ortam değişkenine veya Azure Key Vault gibi güvenli bir kaynağa. WinForms ve WPF'de App.config kullanılır ve hassas bölümler Protected Configuration ile korunur.
Name=ConnectionStrings:X ne anlama geliyor?
EF araçlarına "bağlantı dizesini doğrudan buraya yazmıyorum, projenin yapılandırmasındaki şu anahtardan oku" demektir. Scaffolding komutlarında kullanılır ve hem gizli bilginin komut satırına yazılmasını hem de üretilen koda gömülmesini önler.
Migration bundle bağlantı dizesini nereden alır?
Varsayılan olarak uygulamanızın yapılandırmasından. Belgelere göre farklı bir veritabanını güncellemek için bağlantı dizesini --connection seçeneğiyle verebilirsiniz; üretimde bu değerin dağıtım sisteminin gizli bilgi deposundan gelmesi önerilir.
Bağlantı havuzu boyutunu EF Core'da nasıl değiştiririm?
EF Core'da değil, veritabanı sürücüsünde. Belgelere göre EF bağlantı havuzunu sürücüye bırakır; ADO.NET sürücülerinde havuz parametreleri genellikle bağlantı dizesinde ayarlanır. Kullandığınız sürücünün belgesindeki anahtar adlarına bakın.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: EF Core öğrenme rehberi · DbContext yapılandırma · Migration'ları production'a uygulama · .NET web hosting rehberi