Eqbal Sohrabi
Eqbal Sohrabi

Reputation: 841

Get Entity Framework Model first Entity Name dynamic

I want to do something like this : Get Column name of an Entity in Entity Framework.

I don't want directly using Entity Name , I want to pass Entity-Name to method as string.

 public HttpResponseMessage GetColumnName(string MyClassName)
{

    var db = new DAL.MyEntities();
    var names = typeof(db.MyClassName).GetProperties()
    .Select(property => property.Name)
    .ToArray();

    return new HttpRequestMessage().CreateResponse(HttpStatusCode.OK, names, new HttpConfiguration().Formatters.JsonFormatter);

}

Note : I don't want to use switch-case or If-else .

Why I need this ? I have to return data in an API as JSON . We created a method that convert Entity Models to our class without any relation :

Entity Class:

public partial class foo
{
    public foo()
    {
        this.parent = new HashSet<parent>();
        this.child = new HashSet<child>();
    }

    public int id { get; set; }
    public string title { get; set; }

    public virtual ICollection<parent> parent { get; set; }
    public virtual ICollection<child> child { get; set; }

}

I want to call this API:

public HttpResponseMessage GetFooData()
{
    var db = new DAL.MyEntities();
    var data = db.foos.ToList();
    return new HttpRequestMessage().CreateResponse(HttpStatusCode.OK, data, new HttpConfiguration().Formatters.JsonFormatter);
}

If I Return a List<foo> data will got this error :

The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.

to resolve this I have to create another model same as Entity model without any child and parent like this :

public partial class Myfoo
{
    public int id { get; set; }
    public string title { get; set; }

}

Then I will loop on List<foo> and fill List<Myfoo> , then I will return List<Myfoo>.

Now creating this class wasting my time every day and I want to create a Generator that create MyFoo and Generator to fill Lis<MyFoo> with List<Foo> .

Upvotes: 0

Views: 956

Answers (2)

Eqbal Sohrabi
Eqbal Sohrabi

Reputation: 841

My problem resolved as shown below :

public List<string> GetServiceModelProprty(string EntityName, bool ShowGeneric = false)
    {

        List<string> ProNames = new List<string>();
        var names = Type.GetType(EntityName)
            .GetProperties()
            .Select(p => p.Name).ToArray();
        ProNames.AddRange(names);
        return ProNames;
    }

I get all property from Entity , note that EntityName should contain NameSpace like : DAL.MyClassName

Also this is my mapper Generator :

public class MapperGenerator
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="FullEntityName">Entity Name in  DataBase Contain NameSpace</param>
    /// <param name="ServiceModelName"></param>
    /// <param name="MapperFunctionName"></param>
    /// <param name="NeedHtmlBreak"></param>
    /// <returns></returns>
    public string GenerateMapperString(string FullEntityName, string ServiceModelName, string MapperFunctionName, bool NeedHtmlBreak)
    {

        List<string> PropNames = new List<string>();
        var names = new ECBVendorDAL.DataMapperGenerator().GetServiceModelProprty(FullEntityName);
        PropNames.AddRange(names);
        // DB Entity
        string EntityName = FullEntityName.Split('.')[1];
        //Service Model
        string B_SM = ServiceModelName;
        // Function In Mapper
        string strFunc = MapperFunctionName;

        StringBuilder sb = new StringBuilder();
        // A>B
        sb.Append(GetModelString(PropNames, EntityName, ServiceModelName, strFunc, NeedHtmlBreak, false));
        // B>A
        sb.Append(GetModelString(PropNames, ServiceModelName, EntityName, strFunc, NeedHtmlBreak, false));
        //List<A> to List<B>
        sb.Append(GetModelString(PropNames, EntityName, ServiceModelName, strFunc, NeedHtmlBreak, true));
        //List<B> to List<A>
        sb.Append(GetModelString(PropNames, ServiceModelName, EntityName, strFunc, NeedHtmlBreak, true));

        return sb.ToString();
    }

    private string GetModelString(List<string> ColunNames, string ReturnedClass, string PassedClass, string strFunctionName, bool ApplyHtmlBr, bool IsList = false)
    {
        string htmlBr = ApplyHtmlBr ? "<br />" : string.Empty;
        StringBuilder Sb = new StringBuilder();
        if (IsList)
        {
            #region dbModelName To dbServiceModelName
            //public static List<VendorServiceModel> GetVendorServiceModel(ICollection<ECB_Vendor> input)
            Sb.Append("<xmp>");
            Sb.Append(string.Format("public static List<{0}> {2}(ICollection<{1}> input)", ReturnedClass, PassedClass, strFunctionName));
            Sb.Append("</xmp>" + htmlBr);
            Sb.Append("{" + htmlBr);
            // -    -   -   -   - List<VendorServiceModel> result = new List<VendorServiceModel>();
            Sb.Append("<xmp>");
            Sb.Append(string.Format(" List<{0}> result = new List<{0}>();", ReturnedClass));
            Sb.Append("</xmp>" + htmlBr);
            Sb.Append("foreach (var item in input)" + htmlBr);
            Sb.Append("{" + htmlBr);
            Sb.Append("<xmp>");
            Sb.Append(string.Format("result.Add({0}(item));", strFunctionName));
            Sb.Append("</xmp>" + htmlBr);
            Sb.Append("}" + htmlBr);
            Sb.Append("return result;" + htmlBr);
            Sb.Append("}" + htmlBr);
            #endregion
        }
        else
        {
            #region One - PassedClass To ReturnedClass

            Sb.Append(htmlBr);
            Sb.Append(string.Format("public static {0} {2}({1} input)" + htmlBr, ReturnedClass, PassedClass, strFunctionName));
            Sb.Append("{" + htmlBr);
            Sb.Append(string.Format("return new {0}()", ReturnedClass));
            Sb.Append("{" + htmlBr);
            foreach (var item in ColunNames)
            {
                Sb.Append(string.Format("{0} = input.{0} , " + htmlBr, item));
            }
            Sb.Append("};" + htmlBr);
            Sb.Append("}" + htmlBr);
            Sb.Append(htmlBr);

            #endregion

        }

        return Sb.ToString();

    }

}

Upvotes: 0

pwas
pwas

Reputation: 3373

If you had standard defined DbContext:

public class MyEntities : DbContext
{
    //..
    public DbSet<MyEntity> MyEntites { get; set; }

    //..
}

you need to use reflection

var db = new DAL.MyEntities();
var type = db.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)
                       .Where(pr => pr.PropertyType.IsGenericType)
                       .Where(pr => pr.PropertyType.GetGenericTypeDefinition() ==  
                                           typeof(DbSet<>))
                       .Select(pr => pr.PropertyType.GetGenericArguments().Single())
                       .SingleOrDefault(t => t.Name == MyClassName);
if (type == null) / * type not found case */ ;

var names = type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
                .Select(property => property.Name)
                .ToArray();

Upvotes: 1

Related Questions