Skip to content

Entity Framework - Complex Types

Giriş

Entity Framework'te Complex Types (Karmaşık Tipler), bir entity'nin içinde yer alan ve kendi başına bir entity olmayan, ancak birden fazla özellik içeren yapılardır. Mid-level geliştiriciler için bu kavramın anlaşılması ve etkin kullanımı önemlidir.

Complex Types'ın Önemi

  1. Domain Model
  2. Daha iyi organizasyon
  3. Daha iyi encapsulation
  4. Daha iyi okunabilirlik
  5. Daha iyi bakım

  6. Veri Yapısı

  7. Daha iyi veri organizasyonu
  8. Daha iyi veri bütünlüğü
  9. Daha iyi veri erişimi
  10. Daha iyi veri yönetimi

  11. Bakım

  12. Daha az kod tekrarı
  13. Daha kolay test edilebilirlik
  14. Daha iyi modülerlik
  15. Daha kolay genişletilebilirlik

Complex Types Özellikleri

  1. Temel Complex Type

    public class Address
    {
        public string Street { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string ZipCode { get; set; }
    }
    
    public class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public Address BillingAddress { get; set; }
        public Address ShippingAddress { get; set; }
    }
    

  2. Complex Type Konfigürasyonu

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Customer>(entity =>
        {
            entity.OwnsOne(c => c.BillingAddress, address =>
            {
                address.Property(a => a.Street).HasColumnName("BillingStreet");
                address.Property(a => a.City).HasColumnName("BillingCity");
                address.Property(a => a.State).HasColumnName("BillingState");
                address.Property(a => a.ZipCode).HasColumnName("BillingZipCode");
            });
    
            entity.OwnsOne(c => c.ShippingAddress, address =>
            {
                address.Property(a => a.Street).HasColumnName("ShippingStreet");
                address.Property(a => a.City).HasColumnName("ShippingCity");
                address.Property(a => a.State).HasColumnName("ShippingState");
                address.Property(a => a.ZipCode).HasColumnName("ShippingZipCode");
            });
        });
    }
    

  3. Complex Type Validasyonu

    public class Address
    {
        private string _street;
        private string _city;
        private string _state;
        private string _zipCode;
    
        public string Street
        {
            get => _street;
            set
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentException("Street cannot be empty");
                _street = value;
            }
        }
    
        public string City
        {
            get => _city;
            set
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentException("City cannot be empty");
                _city = value;
            }
        }
    
        public string State
        {
            get => _state;
            set
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentException("State cannot be empty");
                _state = value;
            }
        }
    
        public string ZipCode
        {
            get => _zipCode;
            set
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentException("ZipCode cannot be empty");
                _zipCode = value;
            }
        }
    }
    

Complex Types Kullanımı

  1. Entity İçinde Kullanım

    public class Order
    {
        public int Id { get; set; }
        public DateTime OrderDate { get; set; }
        public Address ShippingAddress { get; set; }
        public Address BillingAddress { get; set; }
        public List<OrderItem> Items { get; set; }
    }
    
    public class OrderItem
    {
        public int Id { get; set; }
        public int OrderId { get; set; }
        public string ProductName { get; set; }
        public decimal Price { get; set; }
        public int Quantity { get; set; }
    }
    

  2. DbContext Konfigürasyonu

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Order>(entity =>
        {
            entity.OwnsOne(o => o.ShippingAddress, address =>
            {
                address.Property(a => a.Street).HasColumnName("ShippingStreet");
                address.Property(a => a.City).HasColumnName("ShippingCity");
                address.Property(a => a.State).HasColumnName("ShippingState");
                address.Property(a => a.ZipCode).HasColumnName("ShippingZipCode");
            });
    
            entity.OwnsOne(o => o.BillingAddress, address =>
            {
                address.Property(a => a.Street).HasColumnName("BillingStreet");
                address.Property(a => a.City).HasColumnName("BillingCity");
                address.Property(a => a.State).HasColumnName("BillingState");
                address.Property(a => a.ZipCode).HasColumnName("BillingZipCode");
            });
    
            entity.HasMany(o => o.Items)
                .WithOne()
                .HasForeignKey(i => i.OrderId);
        });
    }
    

  3. Complex Type Dönüşümleri

    // Complex Type to String
    public static class AddressExtensions
    {
        public static string ToString(this Address address)
        {
            return $"{address.Street}, {address.City}, {address.State} {address.ZipCode}";
        }
    }
    
    // String to Complex Type
    public static class AddressParser
    {
        public static Address Parse(string addressString)
        {
            var parts = addressString.Split(',');
            if (parts.Length != 3)
                throw new ArgumentException("Invalid address format");
    
            var cityStateZip = parts[2].Trim().Split(' ');
            if (cityStateZip.Length != 3)
                throw new ArgumentException("Invalid address format");
    
            return new Address
            {
                Street = parts[0].Trim(),
                City = parts[1].Trim(),
                State = cityStateZip[0],
                ZipCode = cityStateZip[2]
            };
        }
    }
    

Best Practices

  1. Complex Type Tasarımı
  2. Single Responsibility
  3. Immutability
  4. Validation
  5. Business logic

  6. Güvenlik

  7. Input validation
  8. Data integrity
  9. Access control
  10. Audit logging

  11. Performans

  12. Memory usage
  13. Query optimization
  14. Lazy loading
  15. Caching

  16. Bakım

  17. Code organization
  18. Documentation
  19. Testing
  20. Versioning

Mülakat Soruları

Temel Sorular

  1. Entity Framework'te Complex Type nedir?
  2. Cevap: Complex Type, bir entity'nin içinde yer alan ve kendi başına bir entity olmayan, ancak birden fazla özellik içeren yapılardır.

  3. Entity Framework'te Complex Type ve Entity arasındaki fark nedir?

  4. Cevap: Entity'lerin kendi tabloları vardır ve kimlikleri vardır, Complex Type'ların kendi tabloları yoktur ve entity'lerin içinde yer alırlar.

  5. Entity Framework'te Complex Type nasıl konfigüre edilir?

  6. Cevap: DbContext.OnModelCreating metodunda OwnsOne metodu kullanılarak konfigüre edilir.

  7. Entity Framework'te Complex Type ne zaman kullanılır?

  8. Cevap: Bir entity'nin içinde yer alan ve kendi başına bir entity olmayan, ancak birden fazla özellik içeren yapılar için kullanılır.

  9. Entity Framework'te Complex Type performansı nasıl etkiler?

  10. Cevap: Memory kullanımını artırabilir ancak veri organizasyonunu ve kod kalitesini artırır.

Teknik Sorular

  1. Temel Complex Type nasıl oluşturulur?
  2. Cevap:

    public class Address
    {
        public string Street { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string ZipCode { get; set; }
    }
    

  3. Complex Type DbContext'te nasıl konfigüre edilir?

  4. Cevap:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Customer>(entity =>
        {
            entity.OwnsOne(c => c.Address, address =>
            {
                address.Property(a => a.Street).HasColumnName("Street");
                address.Property(a => a.City).HasColumnName("City");
                address.Property(a => a.State).HasColumnName("State");
                address.Property(a => a.ZipCode).HasColumnName("ZipCode");
            });
        });
    }
    

  5. Complex Type validasyonu nasıl yapılır?

  6. Cevap:

    public class Address
    {
        private string _street;
        private string _city;
        private string _state;
        private string _zipCode;
    
        public string Street
        {
            get => _street;
            set
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentException("Street cannot be empty");
                _street = value;
            }
        }
    
        // Diğer property'ler için benzer validasyonlar
    }
    

  7. Complex Type equality nasıl sağlanır?

  8. Cevap:

    public class Address
    {
        public string Street { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string ZipCode { get; set; }
    
        public override bool Equals(object obj)
        {
            if (obj is Address other)
            {
                return Street == other.Street &&
                       City == other.City &&
                       State == other.State &&
                       ZipCode == other.ZipCode;
            }
            return false;
        }
    
        public override int GetHashCode()
        {
            return HashCode.Combine(Street, City, State, ZipCode);
        }
    }
    

  9. Complex Type dönüşümleri nasıl yapılır?

  10. Cevap:
    public static class AddressExtensions
    {
        public static string ToString(this Address address)
        {
            return $"{address.Street}, {address.City}, {address.State} {address.ZipCode}";
        }
    }
    
    public static class AddressParser
    {
        public static Address Parse(string addressString)
        {
            var parts = addressString.Split(',');
            if (parts.Length != 3)
                throw new ArgumentException("Invalid address format");
    
            var cityStateZip = parts[2].Trim().Split(' ');
            if (cityStateZip.Length != 3)
                throw new ArgumentException("Invalid address format");
    
            return new Address
            {
                Street = parts[0].Trim(),
                City = parts[1].Trim(),
                State = cityStateZip[0],
                ZipCode = cityStateZip[2]
            };
        }
    }
    

İleri Seviye Sorular

  1. Entity Framework'te Complex Type performansı nasıl optimize edilir?
  2. Cevap:

    • Memory kullanımı optimizasyonu
    • Query optimizasyonu
    • Lazy loading
    • Caching stratejileri
    • Index kullanımı
  3. Entity Framework'te distributed sistemlerde Complex Type nasıl yönetilir?

  4. Cevap:

    • Serialization
    • Versioning
    • Migration
    • Consistency
    • Conflict resolution
  5. Entity Framework'te high concurrency senaryolarında Complex Type nasıl yönetilir?

  6. Cevap:

    • Immutability
    • Thread safety
    • Atomic operations
    • Versioning
    • Conflict resolution
  7. Entity Framework'te Complex Type monitoring ve profiling nasıl yapılır?

  8. Cevap:

    • Memory profiling
    • Performance metrics
    • Resource monitoring
    • Profiling tools
    • Health checks
  9. Entity Framework'te custom Complex Type stratejileri nasıl geliştirilir?

  10. Cevap:
    • Custom equality
    • Custom validation
    • Custom serialization
    • Custom conversion
    • Custom optimization