Sie sind hier: Weblog

Self Tracking Entities mit Code Only implementieren

Foto ,
25.08.2011 13:48:00

// --- Wiederverwendbarer Teil --------------

public enum DetachedEntityState
{
    New, Updated, Deleted, Unchanged
}

public interface IEntity
{
    DetachedEntityState State { get; set; }
}

public static class StateTrackingHelper
{

    public static void ApplyStates<T>(this ICollection<T> entities, DbContext ctx) where T : class, IEntity 
    {
        foreach (var e in entities)
        {
            ApplyState(e, ctx);
        }
    }

    public static void ApplyState<T>(this T entity, DbContext ctx) where T : class, IEntity
    {
        switch (entity.State)
        {
            case DetachedEntityState.New:
                ctx.Entry<T>(entity).State = System.Data.EntityState.Added;
                break;
            case DetachedEntityState.Updated:
                ctx.Entry<T>(entity).State = System.Data.EntityState.Modified;
                break;
            case DetachedEntityState.Deleted:
                ctx.Entry<T>(entity).State = System.Data.EntityState.Deleted;
                break;
        }
    }

    public static ICollection<T> ResetStates<T>(this ICollection<T> entities) where T : class, IEntity
    {
        foreach (var e in entities)
        {
            ResetState(e);
        }
        return entities;
    }

    public static void ResetState<T>(this T entity) where T : class, IEntity
    {
        entity.State = DetachedEntityState.Unchanged;
    }
        
}

// --- Anwendung --------------

public class Region: IEntity
{
    public Region()
    {
        Hotels = new List<Hotel>();
        Top10Hotels = new List<Hotel>();
    }

    private int _RegionId;
    public int RegionId
    {
        get
        {
            return _RegionId;
        }
        set
        {
            if (_RegionId != value) {
                _RegionId = value;
                this.State = DetachedEntityState.Updated; 
            }
        }
    }
    private string _Bezeichnung;
    public string Bezeichnung
    {
        get
        {
            return _Bezeichnung;
        }
        set
        {
            if (_Bezeichnung != value) {
                _Bezeichnung = value;
                this.State = DetachedEntityState.Updated; 
            }
        }
    }

    private ICollection<Hotel> _Hotels;

    public virtual ICollection<Hotel> Hotels
    {
        get
        {
            return _Hotels;
        }
        set
        {
            if (_Hotels != value) {
                _Hotels = value;
                this.State = DetachedEntityState.Updated; 
            }

        }
    }
    private ICollection<Hotel> _Top10Hotels;
    public virtual ICollection<Hotel> Top10Hotels
    {
        get
        {
            return _Top10Hotels;
        }
        set
        {
            if (_Top10Hotels != value) {
                _Top10Hotels = value;
                this.State = DetachedEntityState.Updated; 
            }

                 
        }
    }

    private DetachedEntityState _State;
    [NotMapped]
    public DetachedEntityState State
    {
        get
        {
            return _State;
        }
        set
        {
            _State = value;
        }
    }
}

public class Hotel : IEntity
{
    private int _HotelId;
    public int HotelId
    {
        get
        {
            return _HotelId;
        }
        set
        {

            if (_HotelId != value) {
                _HotelId = value;
                this.State = DetachedEntityState.Updated; 
            }

            
        }
    }
    private string _Bezeichnung;
    public string Bezeichnung
    {
        get
        {
            return _Bezeichnung;
        }
        set
        {
            if (_Bezeichnung != value) {
                _Bezeichnung = value;
                this.State = DetachedEntityState.Updated; 
            }
                
        }
    }
    private int _Sterne;
    public int Sterne
    {
        get
        {
            return _Sterne;
        }
        set
        {

            if (_Sterne != value) {
                _Sterne = value;
                this.State = DetachedEntityState.Updated; 
            }
        }
    }

    private int _RegionId;
    public int RegionId
    {
        get
        {
            return _RegionId;
        }
        set
        {
            if (_RegionId != value) {
                _RegionId = value;
                this.State = DetachedEntityState.Updated; 
            }
        }
    }

    private Region _Region;
    [ForeignKey("RegionId"), InverseProperty("Hotels")]
    public virtual Region Region
    {
        get
        {
            return _Region;
        }
        set
        {
            if (_Region != value) {
                _Region = value;
                this.State = DetachedEntityState.Updated; 
            }
        }
    }

    private DetachedEntityState _State;
    [NotMapped]
    public DetachedEntityState State
    {
        get
        {
            return _State;
        }
        set
        {
            _State = value;
        }
    }
        
}

public class WellnessHotel : Hotel
{
    private int _AnzahlSaunen;
    public int AnzahlSaunen
    {
        get
        {
            return _AnzahlSaunen;
        }
        set
        {
            if (_AnzahlSaunen != value) {
                _AnzahlSaunen = value;
                this.State = DetachedEntityState.Updated; 
            }
                
        }
    }
    private int _AnzahlThermalBecken;
    public int AnzahlThermalBecken
    {
        get
        {
            return _AnzahlThermalBecken;
        }
        set
        {
            if (_AnzahlThermalBecken != value) {
                _AnzahlThermalBecken = value;
                this.State = DetachedEntityState.Updated; 
            }
        }
    }
}

public class HotelDbContext : DbContext
{
    public HotelDbContext(): base("CodeOnlyHotelDb") { } 

    public DbSet<Hotel> Hotels { get; set; }
    public DbSet<Region> Regionen { get; set; }
}

public class RegionDAO
{

    public List<Region> FindAll()
    {
        using (var ctx = new HotelDbContext())
        {
            var result = ctx.Regionen.Include("Hotels").ToList();
            result.ResetStates();
            return result;
        }

    }

    public void UpdateRegion(Region r)
    {
        using (var ctx = new HotelDbContext())
        {
            ctx.Regionen.Attach(r);

            r.ApplyState(ctx);
            r.Hotels.ApplyStates(ctx);
                
            ctx.SaveChanges();

            r.ResetState();
            r.Hotels.ResetStates();
        }
    }

    public void SaveRegion(Region r1)
    {
        using (var ctx = new HotelDbContext())
        {
            ctx.Regionen.Add(r1);
            ctx.SaveChanges();
        }
    }



}

class Program
{
    static void Main(string[] args)
    {
        Database.SetInitializer(new DropCreateDatabaseAlways<HotelDbContext>());

        CreateSaveModifySaveDemo();
        LoadShowModifySaveDemo();
        LoadShowModifySaveDemo();

        Console.WriteLine("fertig!");
        Console.ReadLine();

    }

    private static void CreateSaveModifySaveDemo()
    {
        var dao = new RegionDAO();

        Region r1 = new Region { Bezeichnung = "Graz" };
        Hotel h1 = new Hotel { Bezeichnung = "Hotel zur Post", Sterne = 2 };

        WellnessHotel h2 = new WellnessHotel
        {
            Bezeichnung = "Hotel zur Wellness",
            Sterne = 4,
            AnzahlSaunen = 3,
            AnzahlThermalBecken = 4
        };

        r1.Hotels.Add(h1);
        r1.Hotels.Add(h2);
        r1.Top10Hotels.Add(h2);

        dao.SaveRegion(r1);

        h2.Sterne++;
        r1.Bezeichnung += "!"; // kleine Änderung

        dao.UpdateRegion(r1);
    }

    private static void LoadShowModifySaveDemo()
    {
        var dao = new RegionDAO();

        var regionen = dao.FindAll();
        foreach (var r in regionen)
        {
            Console.WriteLine(r.Bezeichnung);
            r.Bezeichnung += "$"; // kleine Änderung
            int i = 0;
            foreach (var h in r.Hotels)
            {
                Console.WriteLine("    " + h.Bezeichnung + ", Sterne: " + h.Sterne);
                if (i++ % 2 == 0) h.Bezeichnung += "$"; // kleine Änderung
            }
            Console.WriteLine();
            dao.UpdateRegion(r);
        }
            
    }

}