Search code examples
c#asp.netentity-frameworklinqodata

Using $expand between customModels


I have:

Visual Studio 2015+Asp.Net web API+MySql Database+Ado.net Datamodel+EF 6+Odata v3

I have 2 customModels getting Data from other "myDBEntities"

../api/myCustomModel1 - works fine

../api/myCustomModel2 - works fine

../api/myCustomModel1?$expand=myCustomModel2 - crash

Error:

The specified type member 'myCustomModel2' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

myCustomModels:

public class myCustomModel1
{
    public byte idL{ get; set; }
    [Key]
    public int idP{ get; set; }
    public string Name { get;set ;  }

    public virtual ICollection<myCustomModel2> myCustomModel2{ get; set; }
}


public class myCustomModel2
{
    public byte idL{ get; set; }
    [ForeignKey("myCustomModel1")]
    public int fk_idP { get; set; }
    public myCustomModel1 myCustomModel1 { get; set; }
    [Key]
    public long idT{ get; set; }
    public string Name { get; set; }       
}

CustomModel1 Controller:

    private static ODataValidationSettings _validationSettings = new ODataValidationSettings();
    private myDBEntities db = new myDBEntities();

    // GET: api/myCustomModel1
    [EnableQuery]
    public IQueryable<myCustomModel1> GetmyCustomModel1()
    {

        var x = (from p in db.table1
                 join l in db.table2 on p.column equals l.column 
                 select new myCustomModel1{ idL= p.idL, idP= p.idP, Name = String.Concat(l.Name, p.Name) });

        return x;
    }

CustomModel2 Controller:

    private static ODataValidationSettings _validationSettings = new ODataValidationSettings();


    private myDBEntities db = new myDBEntities ();

    // GET: api/myCustomModel2
    [EnableQuery]
    public IQueryable<myCustomModel2> GetmyCustomModel2()
    {

        var x = (from t in db.table3
                 join l in db.table2 on t.column equals l.column
                 select new myCustomModel2{ idL= t.idL, fk_idP= t.idP,idT= t.idT, Name = String.Concat(l.Name, t.Name) });
        return x;
    }

My Question is: What needs to be done to use

"../api/myCustomModel1?$expand=myCustomModel2" ?


Solution

  • I solved this problem this way:

    My Custom Models:

    public class myCustomModel1
    {
       public byte idL { get; set; }
       [Key]
       public int idP { get; set; }
       public string Name { get; set; }
       public virtual List<myCustomModel2> CustomModel2{ get; set; }
    }
    
    public class myCustomModel2
    {
       public int idData { get; set; }
    }
    

    My controller:

    public class myCustomModel1Controller: ODataController
    {
        private static ODataValidationSettings _validationSettings = new ODataValidationSettings();       
        private IRepository _repo = new Repository();
    
        [EnableQuery]
        public IEnumerable<myCustomModel1> GetmyCustomModel1([FromODataUri] int key)
        {          
            return _repo.FetchDataForcustomModel1(key);
        }
    }
    

    my Interface & Repository:

    public interface IRepository
    {
       IEnumerable<myCustomModel1> FetchDataForcustomModel1(int key);
    }
    public class Repository : IRepository
    {
       private my_dbEntities db = new my_dbEntities(); //Created with Entity Framework - needed to fill my model with database data
    
       public IEnumerable<myCustomModel1> FetchDataForcustomModel1(int key);
       {                   
            IEnumerable<myCustomModel1> myModelData= (from d in db.table1                           
                                  where d.idD == key                                 
                                  select new myCustomModel1
                                  {
                                     idL = d.idL,
                                     idP = d.idP,
                                     Name = d.Name
                                     CustomModel2= (from l in db.table2
                                              where l.fkidD == d.idD                                           
                                              select new myCustomModel2
                                              {
                                                  idData = l.fkidD                                             
                                              }).ToList()
                                  }).ToList();
            return myModelData;
    
      }
    }
    

    Added EntitySet to WebApiConfig.cs

        builder.EntitySet<myCustomModel1>("myCustomModel1");
        builder.EntitySet<myCustomModel2>("myCustomModel2");
    

    Now i can use: /api/myCustomModel1?$expand=CustomModel2

    If you want to have "CustomModel2" autoexpanded remove the EntitySet for "myCustomModel2" in WebApiConfig.cs

    I hope this answer is helpful