简体   繁体   中英

How to set this from Entity Framework using Linq

A while back, I fell into the fat controller trap when I was first working with MVC. My first app used EF4 to make all the models I needed. I just put all my logic into my controller actions. While it worked, it's definitely not the best practice way. To do it the right way I started trying to build my models based on my EF objects in an effort to follow the skinny controller concept.

I've run into a roadblock in trying to find the best way to populate my models. Is there a way to run a LINQ query and have it populate your model without having to iterate through the properties to set to another class?

Something like this:

// from EF model built from database
public class MyEFObject
{
    public int ID {get; set;}
    public string Name {get; set;}
    public string Title {get; set;}
}

public class MyObjectModel : MyEFObject
{
    private Entities _data = new Entities();
    public MyObjectModel(int? id)
    {
        if(id.HasValue) // get an existing record
        {
           this = _data.MyEFObjects.Where(m => m.ID.Equals(id)).Single();
           // or populate right out of the query
           _data.MyEFObjects.Where(m => m.ID.Equals(id))
                         .Select(o => new {
                            this.ID = o.ID,
                            this.Name = o.Name,
                            this.Title = o.Title
                          }); 
        }
        else
        {
           // set defaults for a new MyObjectModel
        }  
    }

    public void Save()
    {
        // takes the current object and saves changes
    }
}

I know you can add a function to the EF Entity object, but I like having the option to Create or Update all tied up in one call (Save method). I don't see the point messing with a model if I have to essentially recreate what I already have from my EF Object. If I simply have a method on a class that accepts a populated object, the concept of a usable model for my views is negated.

What you could do is have a domain model, ef model and and adapter . I think this keeps the code pretty clean and nicely separates the mapping logic.

//Domain model to decouple from EF
public class MyObjectModel
{ 
    public int ID {get; set;} 
    public string Name {get; set;} 
    public string Title {get; set;} 
} 

//Auto generated Entity Framework class
public class MyEFObject
{ 
    public int ID {get; set;} 
    public string Name {get; set;} 
    public string Title {get; set;} 
} 

//Adapter responsible for mapping your data to your domain model
public class MyObjectModelAdapter : MyEFObject
{
    public MyObjectModelAdapter(MyEFObject entity)
    {
        if(entity != null)
        {
            this.ID = entity.ID;
            this.Name = entity.Name;
            this.Title = entity.Title;
        }
        else 
        { 
           // set defaults for a new MyObjectModel 
        }  
    }
}

Then the basic usage would be:

new Entities().MyEFObjects.ToList().Select(x => new MyObjectModelAdapter(x));

OR

new MyObjectModelAdapter(new Entities().MyEFObjects.FirstOrDefault(x => x.ID.Equals(objectId)));

If you specifically require a list of MyObjectModel then you could do the following:

new Entities().MyEFObjects.ToList().Select(x => new MyObjectModelAdapter(x) as MyObjectModel);

OR

new MyObjectModelAdapter(new Entities().MyEFObjects.FirstOrDefault(x => x.ID.Equals(objectId)) as MyObjectModel;

Of course you don't want to chain your entity context together like that, it is just to show usage.

Slauma is right. LINQ to Entities won't accept it. I tried a couple of versions of what was posted and I only found my self with a kludgy mess. I got it to the point where I could set instance values, but by then EF wouldn't register a change had been made and defeating the whole purpose. There may be a way to do this, but as of now, the steps to make it work seem to be overkill.

I ended up with something like this:

public class MyObjectModel : MyEFObject
{
    public void Save(int? id, MyObjectModel model)
    {
       var data = new Entities();
       MyEFObject foo;
       if(id.HasValue)
       {  
           foo = data.MyEFObjects.Where(e => e.ID.Equals(id.Value)).Single();
       }
       else
       {
           foo = new MyEFObject();
       }
       foo.Name = model.Name; 
       foo.Title = model.Title;

       if(!id.HasValue)
       {
          data.MyEFObjects.AddObject(foo);
       }

       data.SaveChanges();
    }
}

I didn't want to have to work with two instances of my model, but it works and I have my lean controller action.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM