0
votes

Have been struggling to fix this for a day now. New to EF as well !!

I require to get my product list together with its child collections.

My Model.tt is in a DataModel.dll and I have reference this in both WCF service and my client. When the entity has child collection, I am getting this error. Guess it is due to the public virtual ICollection of the entity. How can I fix this ?

Trying to put [KnownType(typeof(entity.Name))] in my Model.tt will help ? If so how to get the entity.Name to be passed generically in my Model.tt ?

TRIED :

  1. Put [Serializable] attribute in my Model.tt
  2. LazyLoadingEnabled="false"

ERROR CAPTURED IN TRACE LOG:

Type 'System.Data.Entity.DynamicProxies.Entity_Product_F540EDA252AD69FEA102E0C9AB0167D5397996ADA4679FA9C4089B58B9766924' with data contract name 'Entity_Product_F540EDA252AD69FEA102E0C9AB0167D5397996ADA4679FA9C4089B58B9766924:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the serializer.

There was an error while trying to serialize parameter http://tempuri.org/:GetAllProductResult. The InnerException message was 'Type 'System.Data.Entity.DynamicProxies.Entity_Product_F540EDA252AD69FEA102E0C9AB0167D5397996ADA4679FA9C4089B58B9766924' with data contract name 'Entity_Product_F540EDA252AD69FEA102E0C9AB0167D5397996ADA4679FA9C4089B58B9766924:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the serializer.'. Please see InnerException for more details.

AUTO GENERATED ENTITY :

   [Serializable] 
public partial class Entity_Product
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Entity_Product()
    {
        this.tbl_ManufacturerDetail = new HashSet<Entity_ManufacturerDetail>();
        this.tbl_ProductDetails = new HashSet<Entity_ProductDetails>();
    }

    public int ProductId { get; set; } 
    public string Administration { get; set; }
    public string Manufacturer { get; set; }
    public Nullable<decimal> Price { get; set; } 
    public Nullable<bool> IsEnabled { get; set; }
    public Nullable<System.DateTime> CreatedOn { get; set; }
    public string CreatedBy { get; set; }
    public Nullable<System.DateTime> UpdatedOn { get; set; }
    public string UpdatedBy { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Entity_ManufacturerDetail> tbl_ManufacturerDetail { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Entity_ProductDetails> tbl_ProductDetails { get; set; }
}
1
Have you tried [KnownType(typeof(Entity_ManufacturerDetail))] and [KnownType(typeof(Entity_ProductDetails))]?jegtugado
@JohnEphraimTugado This is DB first EF, so entity is generated from DB. Only way is to add in Model.tt DOnt know how to get the the Entity name dynamically.Anuya
Found that, the Product is referencing ProductDetails and ProductDetails has product id which again references back to Products and so on...same case for Entity_ManufacturerDetail. So it is endless loop. Maybe because of that ? If so, how can I stop this endless referencing ?Anuya
If this is your problem, you could add [DataContract(IsReference = true)] to your class that has endless reference. Please refer to https://stackguides.com/questions/18392402/circular-references-preventing-serialization-of-object-graphAckelry Xu

1 Answers

0
votes

I'm not sure if this is the solution to your problem but this will let you add [KnownType(typeof(entity.Name))] in your Model.tt. Not exactly the entity name but the entity names of each collection navigation property.

This is line 1-70 of my modified Model.tt file. I only changed the lines between the comments //START MODIFICATION and //END MODIFICATION.

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF6.Utility.CS.ttinclude"#><#@ 
 output extension=".cs"#><#

const string inputFile = @"Model.edmx";
var textTransform = DynamicTextTransformation.Create(this);
var code = new CodeGenerationTools(this);
var ef = new MetadataTools(this);
var typeMapper = new TypeMapper(code, ef, textTransform.Errors);
var fileManager = EntityFrameworkTemplateFileManager.Create(this);
var itemCollection = new EdmMetadataLoader(textTransform.Host, textTransform.Errors).CreateEdmItemCollection(inputFile);
var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef);

if (!typeMapper.VerifyCaseInsensitiveTypeUniqueness(typeMapper.GetAllGlobalItems(itemCollection), inputFile))
{
    return string.Empty;
}

WriteHeader(codeStringGenerator, fileManager);

foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection))
{
    fileManager.StartNewFile(entity.Name + ".cs");
    BeginNamespace(code);
#>
//START MODIFICATION
using System.Runtime.Serialization;
<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
<#
    var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity);
    var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity);
    var complexProperties = typeMapper.GetComplexProperties(entity);

    foreach (var navigationProperty in collectionNavigationProperties)
    {
#>
[KnownType(typeof(<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>))]
<#
    }
#>
<#=codeStringGenerator.EntityClassOpening(entity)#>
{
<#
    if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any())
    {
#>
    public <#=code.Escape(entity)#>()
    {
//END MODIFICATION
<#
        foreach (var edmProperty in propertiesWithDefaultValues)
        {
#>
        this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
<#
        }

        foreach (var navigationProperty in collectionNavigationProperties)
        {
#>
        this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
<#
        }

        foreach (var complexProperty in complexProperties)
        {
#>
        this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
<#
        }
#>
    }