UZMAN
EF.Functions — Provider-Specific Fonksiyonlar
LINQ'ta doğrudan yazılamayan veritabanı-özel fonksiyonları (LIKE, DATEPART, Full-Text Search, Vector Search) kullanmak için EF.Functions namespace'ini kullanırsın.
Önemli: SQL Server ve PostgreSQL'in
EF.Functionssetleri tamamen farklıdır. SQL Server'ınDateDiffDay(),Contains(),IsNumeric()gibi fonksiyonları PostgreSQL'de çalışmaz — Npgsql kendi setini sunar.
36.1 String Fonksiyonları
// LIKE — wildcard arama
var products = await context.Products
.Where(p => EF.Functions.Like(p.Name, "%telefon%"))
.ToListAsync();
// SQL: WHERE [p].[Name] LIKE N'%telefon%'
// CONTAINS (Full-Text Search — FTS index gerekir)
var results = await context.Products
.Where(p => EF.Functions.Contains(p.Name, "akıllı AND telefon"))
.ToListAsync();
// SQL: WHERE CONTAINS([p].[Name], N'akıllı AND telefon')
// FREETEXT (doğal dil araması)
var results = await context.Products
.Where(p => EF.Functions.FreeText(p.Description, "ucuz kaliteli telefon"))
.ToListAsync();
// SQL: WHERE FREETEXT([p].[Description], N'ucuz kaliteli telefon')
// Collation — case-sensitive karşılaştırma
var exact = await context.Users
.Where(u => EF.Functions.Collate(u.Username, "SQL_Latin1_General_CP1_CS_AS") == "Admin")
.ToListAsync();
// SQL: WHERE [u].[Username] COLLATE SQL_Latin1_General_CP1_CS_AS = N'Admin'
// ILIKE — Case-insensitive LIKE (SQL Server'da varsayılan CI, PG'de explicit gerekir)
var products = await context.Products
.Where(p => EF.Functions.ILike(p.Name, "%telefon%"))
.ToListAsync();
// SQL: WHERE p.name ILIKE '%telefon%'
// Full-Text Search — tsvector/tsquery (Türkçe dil desteği dahil!)
var results = await context.Products
.Where(p => EF.Functions.ToTsVector("turkish", p.Name)
.Matches(EF.Functions.ToTsQuery("turkish", "akıllı & telefon")))
.ToListAsync();
// SQL: WHERE to_tsvector('turkish', name) @@ to_tsquery('turkish', 'akıllı & telefon')
// Trigram benzerlik araması — typo-tolerant! (pg_trgm extension gerekir)
var similar = await context.Products
.Where(p => EF.Functions.TrigramsAreSimilar(p.Name, "iphne"))
.OrderBy(p => EF.Functions.TrigramsSimilarityDistance(p.Name, "iphne"))
.ToListAsync();
// SQL: WHERE name % 'iphne' ORDER BY name <-> 'iphne'
// → "iPhone" bulur! Fuzzy search.
// Collation — case-sensitive (PG varsayılan case-sensitive, CI istersen collate ekle)
var exact = await context.Users
.Where(u => EF.Functions.Collate(u.Username, "tr-x-icu") == "Admin")
.ToListAsync();
// SQL: WHERE username COLLATE "tr-x-icu" = 'Admin'
Full-Text Search farkı: SQL Server'da FTS Index +
CONTAINSgerekir. PostgreSQL'detsvector+GIN indexile çok daha esnek FTS yapılır — Türkçe stemming, ranking, highlight özellikleri built-in gelir.
36.2 Tarih Fonksiyonları
// DateDiffDay — gün farkı
var recentOrders = await context.Orders
.Where(o => EF.Functions.DateDiffDay(o.OrderDate, DateTime.UtcNow) <= 30)
.ToListAsync();
// SQL: WHERE DATEDIFF(DAY, [o].[OrderDate], GETUTCDATE()) <= 30
// DateDiffMonth
var thisYear = await context.Orders
.Where(o => EF.Functions.DateDiffMonth(o.OrderDate, DateTime.UtcNow) < 12)
.ToListAsync();
// DateDiffHour — son 24 saat
var recent = await context.Logs
.Where(l => EF.Functions.DateDiffHour(l.Timestamp, DateTime.UtcNow) <= 24)
.ToListAsync();
// DateFromParts
var date = EF.Functions.DateFromParts(2024, 6, 15);
// PostgreSQL'de DateDiff YOK — doğrudan aritmetik kullan:
var recentOrders = await context.Orders
.Where(o => DateTime.UtcNow - o.OrderDate < TimeSpan.FromDays(30))
.ToListAsync();
// SQL: WHERE NOW() - order_date < INTERVAL '30 days'
// Son 12 ay
var thisYear = await context.Orders
.Where(o => o.OrderDate >= DateTime.UtcNow.AddMonths(-12))
.ToListAsync();
// SQL: WHERE order_date >= NOW() - INTERVAL '12 months'
// Son 24 saat
var recent = await context.Logs
.Where(l => l.Timestamp >= DateTime.UtcNow.AddHours(-24))
.ToListAsync();
// SQL: WHERE timestamp >= NOW() - INTERVAL '24 hours'
// Tarih oluşturma
var specific = await context.Orders
.Where(o => o.OrderDate == new DateOnly(2024, 6, 15))
.ToListAsync();
// SQL: WHERE order_date = '2024-06-15'
Neden PostgreSQL'de
DateDiffyok? PG tarih aritmetiğini native destekler (date - date = integer,timestamp - timestamp = interval). EF Core bu C# ifadelerini doğrudan SQL'e çevirir — özel fonksiyon gereksiz.
36.3 JSON Fonksiyonları
// SQL Server'da EF.Functions üzerinden JSON sorgusu sınırlı.
// Genelde Raw SQL veya JSON_VALUE ile:
var istanbul = await context.Orders
.Where(o => EF.Property<string>(o, "ShippingAddress") != null)
.FromSqlRaw("SELECT * FROM Orders WHERE JSON_VALUE(ShippingAddress, '$.City') = N'İstanbul'")
.ToListAsync();
// Not: EF Core 10 + SQL Server 2025 ile native json tipi daha iyi destek sağlar (Bölüm 28'e bakın)
// JSON contains — JSONB sütunlarda:
var tagged = await context.Products
.Where(p => EF.Functions.JsonContains(p.Metadata, @"{""featured"": true}"))
.ToListAsync();
// SQL: WHERE metadata @> '{"featured": true}'
// JSON key exists:
var hasKey = await context.Products
.Where(p => EF.Functions.JsonExists(p.Metadata, "discount"))
.ToListAsync();
// SQL: WHERE metadata ? 'discount'
36.4 Diğer Fonksiyonlar
// IsNumeric
var numeric = await context.Products
.Where(p => EF.Functions.IsNumeric(p.Sku))
.ToListAsync();
// SQL: WHERE ISNUMERIC([Sku]) = 1
// DataLength (byte cinsinden veri uzunluğu)
var bigDescriptions = await context.Products
.Where(p => EF.Functions.DataLength(p.Description) > 10000)
.ToListAsync();
// SQL: WHERE DATALENGTH([Description]) > 10000
// Random — rastgele sıralama
var randomProducts = await context.Products
.OrderBy(p => EF.Functions.Random())
.Take(5)
.ToListAsync();
// SQL: ORDER BY NEWID()
// IsNumeric yok — regex ile:
var numeric = await context.Products
.Where(p => Regex.IsMatch(p.Sku, @"^\d+$"))
.ToListAsync();
// SQL: WHERE sku ~ '^\d+$'
// Byte length:
var bigDescriptions = await context.Products
.Where(p => EF.Functions.DataLength(p.Description) > 10000)
.ToListAsync();
// SQL: WHERE octet_length(description) > 10000
// Random — rastgele sıralama
var randomProducts = await context.Products
.OrderBy(p => EF.Functions.Random())
.Take(5)
.ToListAsync();
// SQL: ORDER BY random()
Karşılaştırma Tablosu
| İhtiyaç | SQL Server (EF.Functions) |
PostgreSQL (Npgsql) |
|---|---|---|
| Case-insensitive arama | Like() (varsayılan CI) |
ILike() |
| Full-text search | Contains() / FreeText() |
ToTsVector().Matches(ToTsQuery()) |
| Tarih farkı | DateDiffDay(a, b) |
b - a (doğrudan çıkarma) |
| JSON contains | (Raw SQL) | JsonContains() → @> |
| JSON key exists | (Raw SQL) | JsonExists() → ? |
| Fuzzy/typo search | TrigramsAreSimilar() → % |
|
| Regex match | PATINDEX (sınırlı) |
Regex.IsMatch() → ~ |
| Rastgele sıralama | Random() → NEWID() |
Random() → random() |
| Numerik kontrol | IsNumeric() |
Regex ile |
🆕 EF Core 10 (GA): Vector Search (SQL Server 2025 / Azure SQL)
Gereksinim: SQL Server 2025 / Azure SQL +
Microsoft.Data.SqlClient6.0+ | PostgreSQL:pgvectorextension
AI ve semantic search senaryoları için vektör veri tipi ve benzerlik araması desteği:
// Entity'de vektör property:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
[Column(TypeName = "vector(1536)")] // OpenAI embedding boyutu
public SqlVector<float> Embedding { get; set; }
}
// Embedding oluşturma ve kaydetme:
var embedding = await embeddingGenerator.GenerateVectorAsync("Kablosuz kulaklık");
context.Products.Add(new Product
{
Name = "AirPods Pro",
Embedding = new SqlVector<float>(embedding)
});
await context.SaveChangesAsync();
// Semantic search — en benzer 5 ürünü bul:
var queryVector = await embeddingGenerator.GenerateVectorAsync("bluetooth kulaklık");
var similar = await context.Products
.OrderBy(p => EF.Functions.VectorDistance("cosine", p.Embedding, queryVector))
.Take(5)
.ToListAsync();
-- Üretilen SQL (SQL Server 2025):
SELECT TOP(5) [p].[Id], [p].[Name], [p].[Embedding]
FROM [Products] AS [p]
ORDER BY VECTOR_DISTANCE('cosine', [p].[Embedding], @queryVector);
-- Üretilen SQL (pgvector extension gerekli):
SELECT p.id, p.name, p.embedding
FROM products AS p
ORDER BY p.embedding <=> @queryVector -- cosine distance operatörü
LIMIT 5;
-- pgvector kurulumu:
-- CREATE EXTENSION vector;
-- CREATE INDEX ON products USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
Kullanım alanları: RAG (Retrieval-Augmented Generation), ürün önerisi, benzer doküman bulma, semantic search.
Gereksinimler: SQL Server 2025 veya Azure SQL Database +Microsoft.Data.SqlClient6.0+ | PostgreSQL:pgvectorextension