I have a problem to get the right OpenApi definition aftr update from 5.0.0 to 5.4.1
We had custom Polymorphism filter with 5.0.0 version, but they does not work correct with latest one. So I removed them and started to use GeneratePolymorphicSchemas(). It does what I need for our polymorphic models but not just for them. We have also some other abstract and concrete classes, where we don't need type discriminator. I tried different configurations but without any success. Either the generated definition is wrong or I get error on swagger UI or a server 503 error.
Link to the sample project Sample project
Here are my polimorhic models
namespace SwashbuckleTest.Models
{
public interface ITypeDiscriminator
{
string TypeDiscriminator { get; }
}
public abstract class SurveyStep : ITypeDiscriminator
{
public virtual string Id { get; set; }
public string TypeDiscriminator => GetType().Name;
}
public abstract class SurveyStepResult : ITypeDiscriminator
{
public string Id { get; set; }
public string TypeDiscriminator => GetType().Name;
}
public class BoolStep : SurveyStep
{
private string _id;
public BoolStep()
{
ResultObject = new BoolStepResult();
}
public override string Id
{
get => _id;
set
{
_id = value;
ResultObject.Id = value;
}
}
public string Question { get; set; }
public BoolStepResult ResultObject { get; }
}
public class BoolStepResult : SurveyStepResult
{
public bool Value { get; set; }
}
}
Here other models
namespace SwashbuckleTest.Models
{
public abstract class SomeBaseModel
{
public string BaseValue { get; set; }
}
public class SomeConcreteModel : SomeBaseModel
{
public int ConcreteValue { get; set; }
}
}
and configurations I have tried
options.UseAllOfToExtendReferenceSchemas();
options.GeneratePolymorphicSchemas(t =>
{
var types = t.Is<SurveyStep>() ? new List<Type>() {typeof(BoolStep)}
: t.Is<SurveyStepResult>() ? new List<Type>() {typeof(BoolStepResult)}
: null;
return types;
} , t => t.Is<ITypeDiscriminator>() ? nameof(ITypeDiscriminator.TypeDiscriminator).ToCamelCase() : null);
// or
options.GeneratePolymorphicSchemas(discriminatorSelector: t => t.Is<ITypeDiscriminator>() ? nameof(ITypeDiscriminator.TypeDiscriminator).ToCamelCase() : null);
I found the problem by my self.
The Is<> extension method does not filter abstract classes so we got here endless recursion.
It helped us to generate swagger.json, but we got other problems, that are little bit deeper.
I am creating a reusable library using .NET Core (targeting .NETStandard 1.4) and I am using Entity Framework Core (and new to both). I have an entity class that looks like:
public class Campaign
{
[Key]
public Guid Id { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; }
public JObject ExtendedData { get; set; }
}
and I have a DbContext class that defines the DbSet:
public DbSet<Campaign> Campaigns { get; set; }
(I am also using the Repository pattern with DI, but I don't think that is relevant.)
My unit tests give me this error:
System.InvalidOperationException: Unable to determine the relationship
represented by navigation property 'JToken.Parent' of type
'JContainer'. Either manually configure the relationship, or ignore
this property from the model..
Is there a way to indicate that this is not a relationship but should be stored as a big string?
Going to answer this one differently.
Ideally the domain model should have no idea how data is stored. Adding backing fields and extra [NotMapped] properties is actually coupling your domain model to your infrastructure.
Remember - your domain is king, and not the database. The database is just being used to store parts of your domain.
Instead you can use EF Core's HasConversion() method on the EntityTypeBuilder object to convert between your type and JSON.
Given these 2 domain models:
public class Person
{
public int Id { get; set; }
[Required]
[MaxLength(50)]
public string FirstName { get; set; }
[Required]
[MaxLength(50)]
public string LastName { get; set; }
[Required]
public DateTime DateOfBirth { get; set; }
public IList<Address> Addresses { get; set; }
}
public class Address
{
public string Type { get; set; }
public string Company { get; set; }
public string Number { get; set; }
public string Street { get; set; }
public string City { get; set; }
}
I have only added attributes that the domain is interested in - and not details that the DB would be interested in; I.E there is no [Key].
My DbContext has the following IEntityTypeConfiguration for the Person:
public class PersonsConfiguration : IEntityTypeConfiguration<Person>
{
public void Configure(EntityTypeBuilder<Person> builder)
{
// This Converter will perform the conversion to and from Json to the desired type
builder.Property(e => e.Addresses).HasConversion(
v => JsonConvert.SerializeObject(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }),
v => JsonConvert.DeserializeObject<IList<Address>>(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }));
}
}
With this method you can completely decouple your domain from your infrastructure. No need for all the backing field & extra properties.
The key to making the the Change Tracker function correctly is to implement a ValueComparer as well as a ValueConverter. Below is an extension to implement such:
public static class ValueConversionExtensions
{
public static PropertyBuilder<T> HasJsonConversion<T>(this PropertyBuilder<T> propertyBuilder) where T : class, new()
{
ValueConverter<T, string> converter = new ValueConverter<T, string>
(
v => JsonConvert.SerializeObject(v),
v => JsonConvert.DeserializeObject<T>(v) ?? new T()
);
ValueComparer<T> comparer = new ValueComparer<T>
(
(l, r) => JsonConvert.SerializeObject(l) == JsonConvert.SerializeObject(r),
v => v == null ? 0 : JsonConvert.SerializeObject(v).GetHashCode(),
v => JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(v))
);
propertyBuilder.HasConversion(converter);
propertyBuilder.Metadata.SetValueConverter(converter);
propertyBuilder.Metadata.SetValueComparer(comparer);
propertyBuilder.HasColumnType("jsonb");
return propertyBuilder;
}
}
Example of how this works.
public class Person
{
public int Id { get; set; }
[Required]
[MaxLength(50)]
public string FirstName { get; set; }
[Required]
[MaxLength(50)]
public string LastName { get; set; }
[Required]
public DateTime DateOfBirth { get; set; }
public List<Address> Addresses { get; set; }
}
public class Address
{
public string Type { get; set; }
public string Company { get; set; }
public string Number { get; set; }
public string Street { get; set; }
public string City { get; set; }
}
public class PersonsConfiguration : IEntityTypeConfiguration<Person>
{
public void Configure(EntityTypeBuilder<Person> builder)
{
// This Converter will perform the conversion to and from Json to the desired type
builder.Property(e => e.Addresses).HasJsonConversion<IList<Address>>();
}
}
This will make the ChangeTracker function correctly.
#Michael's answer got me on track but I implemented it a little differently. I ended up storing the value as a string in a private property and using it as a "Backing Field". The ExtendedData property then converted JObject to a string on set and vice versa on get:
public class Campaign
{
// https://learn.microsoft.com/en-us/ef/core/modeling/backing-field
private string _extendedData;
[Key]
public Guid Id { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; }
[NotMapped]
public JObject ExtendedData
{
get
{
return JsonConvert.DeserializeObject<JObject>(string.IsNullOrEmpty(_extendedData) ? "{}" : _extendedData);
}
set
{
_extendedData = value.ToString();
}
}
}
To set _extendedData as a backing field, I added this to my context:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Campaign>()
.Property<string>("ExtendedDataStr")
.HasField("_extendedData");
}
Update: Darren's answer to use EF Core Value Conversions (new to EF Core 2.1 - which didn't exist at the time of this answer) seems to be the best way to go at this point.
For those using EF 2.1 there is a nice little NuGet package EfCoreJsonValueConverter that makes it pretty simple.
using Innofactor.EfCoreJsonValueConverter;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
public class Campaign
{
[Key]
public Guid Id { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; }
public JObject ExtendedData { get; set; }
}
public class CampaignConfiguration : IEntityTypeConfiguration<Campaign>
{
public void Configure(EntityTypeBuilder<Campaign> builder)
{
builder
.Property(application => application.ExtendedData)
.HasJsonValueConversion();
}
}
I have made a solution based on Robert Raboud's contribution. The change made by me is that my implementation uses a HasJsonConversion method that depends on the System.Text.Json package rather than Newtonsofts library:
public static PropertyBuilder<T> HasJsonConversion<T>(this PropertyBuilder<T> propertyBuilder) where T : class, new()
{
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true,
AllowTrailingCommas = true,
PropertyNameCaseInsensitive = true
};
ValueConverter<T, string> converter = new ValueConverter<T, string>
(
v => JsonSerializer.Serialize(v, options),
v => JsonSerializer.Deserialize<T>(v, options) ?? new T()
);
ValueComparer<T> comparer = new ValueComparer<T>
(
(l, r) => JsonSerializer.Serialize(l, options) == JsonSerializer.Serialize(r, options),
v => v == null ? 0 : JsonSerializer.Serialize(v, options).GetHashCode(),
v => JsonSerializer.Deserialize<T>(JsonSerializer.Serialize(v, options), options)
);
propertyBuilder.HasConversion(converter);
propertyBuilder.Metadata.SetValueConverter(converter);
propertyBuilder.Metadata.SetValueComparer(comparer);
propertyBuilder.HasColumnType("LONGTEXT");
return propertyBuilder;
}
Note also that this implementation expects for the column to be LONGTEXT since I am using a MySQL setup.
Here's something I used
Model
public class FacilityModel
{
public string Name { get; set; }
public JObject Values { get; set; }
}
Entity
[Table("facility", Schema = "public")]
public class Facility
{
public string Name { get; set; }
public Dictionary<string, string> Values { get; set; } = new Dictionary<string, string>();
}
Mapping
this.CreateMap<Facility, FacilityModel>().ReverseMap();
DBContext
base.OnModelCreating(builder);
builder.Entity<Facility>()
.Property(b => b.Values)
.HasColumnType("jsonb")
.HasConversion(
v => JsonConvert.SerializeObject(v),
v => JsonConvert.DeserializeObject<Dictionary<string, string>>(v));
Could you try something like this?
[NotMapped]
private JObject extraData;
[NotMapped]
public JObject ExtraData
{
get { return extraData; }
set { extraData = value; }
}
[Column("ExtraData")]
public string ExtraDataStr
{
get
{
return this.extraData.ToString();
}
set
{
this.extraData = JsonConvert.DeserializeObject<JObject>(value);
}
}
here is the migration output:
ExtraData = table.Column<string>(nullable: true),
For developers, who work with EF Core 3.1 and meet such error ("The entity type 'XXX' requires a primary key to be defined. If you intended to use a keyless entity type call 'HasNoKey()'.") the solution is:
Move .HasConversion() method with it's lambda from:
OrderConfiguration : IEntityTypeConfiguration<T> to
OnModelCreating(ModelBuilder modelBuilder) in your DataContext.
// DbContext
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var entityTypes = modelBuilder.Model.GetEntityTypes();
foreach (var entityType in entityTypes)
{
foreach (var property in entityType.ClrType.GetProperties().Where(x => x != null && x.GetCustomAttribute<HasJsonConversionAttribute>() != null))
{
modelBuilder.Entity(entityType.ClrType)
.Property(property.PropertyType, property.Name)
.HasJsonConversion();
}
}
base.OnModelCreating(modelBuilder);
}
Create an attribute to handle the properties of the entities.
public class HasJsonConversionAttribute : System.Attribute
{
}
Create extention class to find Josn properties
public static class ValueConversionExtensions
{
public static PropertyBuilder HasJsonConversion(this PropertyBuilder propertyBuilder)
{
ParameterExpression parameter1 = Expression.Parameter(propertyBuilder.Metadata.ClrType, "v");
MethodInfo methodInfo1 = typeof(Newtonsoft.Json.JsonConvert).GetMethod("SerializeObject", types: new Type[] { typeof(object) });
MethodCallExpression expression1 = Expression.Call(methodInfo1 ?? throw new Exception("Method not found"), parameter1);
ParameterExpression parameter2 = Expression.Parameter(typeof(string), "v");
MethodInfo methodInfo2 = typeof(Newtonsoft.Json.JsonConvert).GetMethod("DeserializeObject", 1, BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder, CallingConventions.Any, types: new Type[] { typeof(string) }, null)?.MakeGenericMethod(propertyBuilder.Metadata.ClrType) ?? throw new Exception("Method not found");
MethodCallExpression expression2 = Expression.Call(methodInfo2, parameter2);
var converter = Activator.CreateInstance(typeof(ValueConverter<,>).MakeGenericType(typeof(List<AttributeValue>), typeof(string)), new object[]
{
Expression.Lambda( expression1,parameter1),
Expression.Lambda( expression2,parameter2),
(ConverterMappingHints) null
});
propertyBuilder.HasConversion(converter as ValueConverter);
return propertyBuilder;
}
}
Entity example
public class Attribute
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
[HasJsonConversion]
public List<AttributeValue> Values { get; set; }
}
public class AttributeValue
{
public string Value { get; set; }
public IList<AttributeValueTranslation> Translations { get; set; }
}
public class AttributeValueTranslation
{
public string Translation { get; set; }
public string CultureName { get; set; }
}
Download Source
For those who are working on entity framework core 5.0 and above. below can work if you are getting error like below
The entity type '{EntityName}' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. The error is asking to define a primary key on the model
Try this
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Person>(
eb =>
{
eb.Property(p => p.Addresses).HasConversion(
v => JsonConvert.SerializeObject(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }),
v => JsonConvert.DeserializeObject<IList<Address>>(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })
);
});
}
----------------- 2022 Update -----------------
Hey there,
Just sharing an update from Dec/2022.
Recently, EF Core 7.0 was launched, containing one of the most awaited features called JSON Columns.
This new feature allows us for mapping aggregates (written from .NET types) into JSON documents.
Just remember that, In EF Core, aggregate types are defined using Owned Entity Types.
https://learn.microsoft.com/en-us/ef/core/modeling/owned-entities
Let's consider this scenario: A object called "LogDetail", that needs to be stored into a single column as a JSON, inside another object (or table) called "Log".
public class Log : BaseEntity
{
public string TraceID { get; set; } = string.Empty;
public string Code { get; set; } = string.Empty;
public LogDetail LogDetail { get; set; } = null!;
public string IpAddress { get; set; } = string.Empty;
}
public class LogDetail
{
public string InnerException { get; set; } = null!;
public string MemberMap { get; set; } = null!;
public string Message { get; set; } = null!;
public string Source { get; set; } = null!;
public string StackTrace { get; set; } = null!;
public string TypeMap { get; set; } = null!;
public string Path { get; set; } = null!;
}
By the end, all that you need is to configure the behavior on your configuration map class:
public sealed class LogMap : IEntityTypeConfiguration<Log>
{
public override void Configure(EntityTypeBuilder<Log> builder)
{
/* Owned Type Configurations */
builder.OwnsOne(e => e.LogDetail, options =>
{
options.ToJson("LOG_DETAIL");
});
}
}
The comment by #Métoule:
Be careful with this approach: EF Core marks an entity as modified only if the field is assigned to. So if you use person.Addresses.Add, the entity won't be flagged as updated; you'll need to call the property setter person.Addresses = updatedAddresses.
made me take a different approach so that this fact is obvious: use Getter and Setter methods, rather than a property.
public void SetExtendedData(JObject extendedData) {
ExtendedData = JsonConvert.SerializeObject(extendedData);
_deserializedExtendedData = extendedData;
}
//just to prevent deserializing more than once unnecessarily
private JObject _deserializedExtendedData;
public JObject GetExtendedData() {
if (_extendedData != null) return _deserializedExtendedData;
_deserializedExtendedData = string.IsNullOrEmpty(ExtendedData) ? null : JsonConvert.DeserializeObject<JObject>(ExtendedData);
return _deserializedExtendedData;
}
You could theoretically do this:
campaign.GetExtendedData().Add(something);
But it's much more clear that That Doesn't Do What You Think It Does™.
If you're using database-first and using some kind of class auto-generator for EF, then the classes will usually be declared as partial, so you can add this stuff in a separate file that won't get blown away the next time you update your classes from your database.
I have a weird situation where I have objects and Lists of objects as part of my entities and contracts to interface with a third-party service. I'm going to try to see if I can replace the actual object class with something more specific in the entities and contracts to get around this, but I am curious if there is a way to get AutoMapper to handle this as is.
Here are some dummy classes:
public class From
{
public object Item { get; set; }
}
public class FromObject
{
public string Value { get; set; }
}
public class To
{
public object Item { get; set; }
}
public class ToObject
{
public string Value { get; set; }
}
And the quick replication:
Mapper.CreateMap<From, To>();
Mapper.CreateMap<FromObject, ToObject>();
From from = new From { Item = new FromObject { Value = "Test" } };
To to = Mapper.Map<To>(from);
string type = to.Item.GetType().Name; // FromObject
Basically, the question is this: Is there a way to get AutoMapper to understand that from.Item is a FromObject and apply the mapping to ToObject? I'm thinking there's probably not a way to make it automatic, since there's nothing that would indicate that to.Item has to be a ToObject, but is there a way to specify during the CreateMap or Map calls that this should be taken into account?
I don't think there is an "automatic" way of doing it, since AutoMapper won't be able to figure out that From.Item is FromObject and To.Item is ToObject.
But, while creating mapping, you can specify that
Mapper.CreateMap<FromObject, ToObject>();
Mapper.CreateMap<From, To>()
.ForMember(dest => dest.Item, opt => opt.MapFrom(src => Mapper.Map<ToObject>(src.Item)));
From from = new From { Item = new FromObject { Value = "Test" } };
To to = Mapper.Map<To>(from);
string type = to.Item.GetType().Name; // ToObject
If you're willing to use an additional interface, this can be accomplished using Include. You can't just map object to object in this fashion, though.
public class From
{
public IItem Item { get; set; }
}
public class FromObject : IItem
{
public string Value { get; set; }
}
public class To
{
public object Item { get; set; }
}
public class ToObject
{
public string Value { get; set; }
}
public interface IItem
{
// Nothing; just for grouping.
}
Mapper.CreateMap<From, To>();
Mapper.CreateMap<IItem, object>()
.Include<FromObject, ToObject>();
From from = new From { Item = new FromObject { Value = "Test" } };
To to = Mapper.Map<To>(from);
string type = to.Item.GetType().Name; // ToObject
I'm trying to use AutoMapper to take data from a class that has prefixes before property names and map it to a second class that doesn't have those prefixes. However, I don't necessarily want it to always strip out that prefix: I just want it to do it for this particular mapping.
My source class looks like this:
public class AdvancedSearchFilterDataModel
{
// ....
public string ServiceMeterNumber { get; set; }
// ....
}
My destination class looks like this:
[DataContract]
public class ServicesAdvancedSearchFilterData : AdvancedSearchFilterData
{
// ....
[DataMember]
public string MeterNumber { get; set; }
// ....
}
When I try to map values like this, it works:
Mapper.Configuration.RecognizePrefixes("Service");
Mapper.CreateMap<AdvancedSearchFilterDataModel, ServicesAdvancedSearchFilterData>();
ServicesAdvancedSearchFilterData servciesFilterData =
Mapper.Map<ServicesAdvancedSearchFilterData>(model);
But I only want "Service" to be recognized as a prefix for certain mappings, since it's also used as a normal part of property names in other mappings. I tried to handle this with a profile, but this didn't work -- no data was mapped:
Mapper.CreateProfile("ServicePrefix").RecognizePrefixes("Service");
Mapper.CreateMap<AdvancedSearchFilterDataModel, ServicesAdvancedSearchFilterData>()
.WithProfile("ServicePrefix");
ServicesAdvancedSearchFilterData servciesFilterData =
Mapper.Map<ServicesAdvancedSearchFilterData>(model);
How can I make it recognize the prefix only when I want it to, either using profiles or some other technique? (I also have other prefixes that I'm going to need it to recognize for other mappings in the same way.)
I achieved this functionality by creating following structure:
I have Person model for my view which is flattened from PersonCombined
public class PersonCombined
{
public Person Person { get; set; }
public Address DefaultAddress { get; set; }
public Contact EmailContact { get; set; }
public Contact PhoneContact { get; set; }
public Contact WebsiteContact { get; set; }
}
public class Person : IWebServiceModel
{
public int ID { get; set; }
public string PersonFirstName { get; set; }
public string PersonSurname { get; set; }
public string PersonDescription { get; set; }
public Nullable<bool> PersonIsActive { get; set; }
}
Then I have separate class for this mapping only that looks like this:
public class PersonCustomMapping : ICustomMapping
{
const string separator = " ";
private static IMappingEngine _MappingEngine;
public IMappingEngine MappingEngine
{
get
{
if (_MappingEngine == null)
{
var configuration = new ConfigurationStore(new TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.Mappers);
configuration.RecognizePrefixes("Person");
configuration.RecognizeDestinationPrefixes("Person");
configuration.CreateMap<Person, MCIACRM.Model.Combine.PersonCombined>();
configuration.CreateMap<MCIACRM.Model.Combine.PersonCombined, Person>();
_MappingEngine = new MappingEngine(configuration);
}
return _MappingEngine;
}
}
}
In my generic view I have mappingEngine property like this:
private IMappingEngine mappingEngine
{
get
{
if (_mappingEngine == null)
{
_mappingEngine = AutoMapper.Mapper.Engine;
}
return _mappingEngine;
}
}
Finally in my generic view constructor i have:
public GenericEntityController(IGenericLogic<S> logic, ICustomMapping customMapping)
: base()
{
this._mappingEngine = customMapping.MappingEngine;
this.logic = logic;
}
And that's how I do mapping:
result = items.Project(mappingEngine).To<R>();
or
logic.Update(mappingEngine.Map<S>(wsItem));
Because I use 1 entity per view I can define custom mapping configuration per entity.
Hope this helps
Here is my data transfer object
public class LoadSourceDetail
{
public string LoadSourceCode { get; set; }
public string LoadSourceDesc { get; set; }
public IEnumerable<ReportingEntityDetail> ReportingEntity { get; set; }
}
public class ReportingEntityDetail
{
public string ReportingEntityCode { get; set; }
public string ReportingEntityDesc { get; set; }
}
And here is my ViewModel
public class LoadSourceViewModel
{
#region Construction
public LoadSourceViewModel ()
{
}
public LoadSourceViewModel(LoadSourceDetail data)
{
if (data != null)
{
LoadSourceCode = data.LoadSourceCode;
LoadSourceDesc = data.LoadSourceDesc;
ReportingEntity = // <-- ? not sure how to do this
};
}
#endregion
public string LoadSourceCode { get; set; }
public string LoadSourceDesc { get; set; }
public IEnumerable<ReportingEntityViewModel> ReportingEntity { get; set; }
}
public class ReportingEntityViewModel
{
public string ReportingEntityCode { get; set; }
public string ReportingEntityDesc { get; set; }
}
}
I'm not sure how to transfer the data from the LoadSourceDetail ReportingEntity to the LoadSourceViewModel ReportingEntity. I'm trying to transfer data from one IEnumerable to another IEnumerable.
I would use AutoMapper to do this:
https://github.com/AutoMapper/AutoMapper
http://automapper.org/
You can easily map collections, see https://github.com/AutoMapper/AutoMapper/wiki/Lists-and-arrays
It would look something like this:
var viewLoadSources = Mapper.Map<IEnumerable<LoadSourceDetail>, IEnumerable<LoadSourceViewModel>>(loadSources);
If you are using this in an MVC project I usually have an AutoMapper config in the App_Start that sets the configuration i.e. fields that do not match etc.
Without AutoMapper you will have to map each property one by one ,
Something like this :
LoadSourceDetail obj = FillLoadSourceDetail ();// fill from source or somewhere
// check for null before
ReportingEntity = obj.ReportingEntity
.Select(x => new ReportingEntityViewModel()
{
ReportingEntityCode = x.ReportingEntityCode,
ReportingEntityDesc x.ReportingEntityDesc
})
.ToList(); // here is 'x' is of type ReportingEntityDetail
You could point it to the same IEnumerable:
ReportingEntity = data.ReportingEntity;
If you want to make a deep copy, you could use ToList(), or ToArray():
ReportingEntity = data.ReportingEntity.ToList();
That will materialize the IEnumerable and store a snapshot in your view model.