Configure Entity Framework to load predefined entity

I have this class

public class Status
{
    private string status;
    public string StatusName
    {
        get
        {
            return status;
        }
    }
    private Status (string _status)
    {
        status = _status;
    }
    public static readonly Status Open = new Status("Open");
    public static readonly Status Closed = new Status("Closed");
}  

      

Using Code First, can I configure EF to load one of the predefined objects (Open, Closed) instead of trying to create a new one? Or is there a better way to achieve similar behavior?

+3


source to share


1 answer


The current version of EF does not provide any bindings to replace object materialization (if you don't download the source, try implementing it yourself). This means that EF will always create its own status and be able to do so, it will also require your class to Status

comply with its rules. I don't know why you need this, but if you really need the same object instances for your statuses, you can hack them.

First you need to change the class Status

for EF:

public class Status{
    // EF needs access to your property
    public string StatusName { get; private set; }

    // EF needs parameterless constructor because it will create instances
    private Status() {}

    private Status (string status) {
        StatusName = status;
    }

    public static readonly Status Open = new Status("Open");
    public static readonly Status Closed = new Status("Closed");
}  

      



Now you need to replace the original Status

one generated by EF with your own:

public Context() : base() {
    var objectContext = ((IObjectContextAdapter)this).ObjectContext;
    objectContext.ObjectMaterialized += OnObjectMaterialized;
}

private void OnObjectMaterialized(object sender, ObjectMaterializedEventArgs args) {
    var objectContext = (ObjectContext)sender;
    var entity = args.Entity as Entity;
    if (entity != null) {
        switch (entity.Status.StatusName) {
            case "Open":
                entity.Status = Status.Open;
                break;
            case "Closed":
                entity.Status = Status.Closed;
                break;
        }

        // This is necessary because previous code made your object modified
        objectContext.DetectChanges();
        var entry = objectContext.ObjectStateManager.GetObjectStateEntry(entity);
        entry.AcceptChanges();
    }
}

      

It's an ugly hack, but if you really need it, you'll need to do something like this.

+1


source







All Articles