entity framework linq include and grouping [duplicate] - c#

This question already has answers here:
Why doesn't Include have any effect?
(2 answers)
Closed 1 year ago.
I'm trying to to do include and group in in one sentence
var instanceIdList = context.
Tracks.
Include("Services").
GroupBy(x => x.ServiceId).
Take(top);
but when I check the result at debug I cant see any of the include values
I tried to do in another way
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
var set = objectContext.CreateObjectSet<Track>();
var instanceIdList = set.Include("Services").GroupBy(x => x.ServiceId);
this is the classes :
Track
public partial class Track
{
public long Id { get; set; }
public System.Guid ServiceId { get; set; }
public Nullable<System.Guid> ServiceInterfaceId { get; set; }
public Nullable<System.Guid> ProviderId { get; set; }
public System.Guid ServiceInstanceId { get; set; }
public System.Guid ActivityParentId { get; set; }
public System.Guid ActivityInstanceId { get; set; }
public int ActivityType { get; set; }
public int ServiceRole { get; set; }
public int TrackOrder { get; set; }
public System.DateTime Datetime { get; set; }
public Nullable<System.Guid> MessageId { get; set; }
public int Status { get; set; }
public Nullable<int> ESBErrorCode { get; set; }
public Nullable<int> ESBTecnicalErrorCode { get; set; }
public string ErrorDescription { get; set; }
public string PortName { get; set; }
public string MachineName { get; set; }
public string ConsumerId { get; set; }
public string ExternalId { get; set; }
public string ConsumerMachineName { get; set; }
public int ServiceBehavior { get; set; }
public virtual Message Message { get; set; }
}
Service
public partial class Service
{
public Service()
{
this.Providers = new HashSet<Provider>();
this.ServiceInterfaces = new HashSet<ServiceInterface>();
}
public System.Guid ServiceId { get; set; }
public string ServiceName { get; set; }
public string ServiceNumber { get; set; }
public Nullable<System.Guid> ModelSchemaId { get; set; }
public virtual ICollection<Provider> Providers { get; set; }
public virtual ICollection<ServiceInterface> ServiceInterfaces { get; set; }
}
but the result is the same
thanks
miki

You also need to put include in the end.
Like this...
var instanceIdList = context.Tracks
.GroupBy(x => x.ServiceId)
.Take(top)
.Include("Services");

You have not defined any navigation property for Services in your Track class, you need to add the following property.
public virtual ICollection<Service> Services { get; set; }

Your Track class has no member accessor called service, so
Include("Services")
won't work.
You need to link to Service from Track, e.g.
public Service Services {get;set;}

Related

Why a list of one type is not getting converted to another? [duplicate]

This question already has answers here:
convert a list of objects from one type to another using lambda expression
(14 answers)
How to cast one compound custom type to another
(2 answers)
C# "cannot implicitly convert type" same model properties
(4 answers)
Closed 2 years ago.
Based on the module name I want to return different lists of different types but problem is that I cannot change the return type for each so I wrote a generic class that has the same properties but it doesn't work that way. How to achieve it.
public List<Models.TasksList> Get(string module)
{
//var query= "";
using (var context = new TasksPlanEntities())
{
if (module == "PEMS")
{
var query = from st in context.PIRTaskLists
select st;
return query.ToList<Models.TasksList>();
else if (module == "PSVMS")
{
var query = from st in context.PSVMS_EnggData
select st;
return query.ToList<Models.TasksList>();
}
}}
TasksList
public class TasksList
{
public int OperationID { get; set; }
public string PIRCode { get; set; }
public string TaskName { get; set; }
public string OperationNo { get; set; }
public string OperationCode { get; set; }
public string OperationDescription { get; set; }
//public static explicit operator TasksList(ObjectResult<GetTaskPlans_EPICOR_Result> v)
//{
// throw new NotImplementedException();
//}
public string Resource { get; set; }
public string NDTResources { get; set; }
public float Duration { get; set; }
public string RequiredEquipmentStatus { get; set; }
public string TimeBaseInterval { get; set; }
public DateTime StartDate { get; set; }
public DateTime LastInspDate { get; set; }
public DateTime NextInspDate { get; set; }
public string FunctionalLocation { get; set; }
}
throws error
Cannot implicitly convert to system.collection.generic.list<Models.TasksList>
Even though the TasksList class has exactly the same names and all. I tried everything but doesn't work out. Why it is so?
Why this is happening since it's the same structure.
Update:
public virtual DbSet<PIRTaskList> PIRTaskLists { get; set; }
public partial class PIRTaskList
{
public int OperationID { get; set; }
public string PIRCode { get; set; }
public string TaskName { get; set; }
public Nullable<int> OperationNo { get; set; }
public Nullable<int> Counter { get; set; }
public string OperationCode { get; set; }
public string OperationDescription { get; set; }
public string Resource { get; set; }
public string NDTResources { get; set; }
public Nullable<double> Duration { get; set; }
public string RequiredEquipmentStatus { get; set; }
public string TimeBaseInterval { get; set; }
public string InspectionType { get; set; }
public string TimeBaseInterval_UOME { get; set; }
public string Description { get; set; }
public Nullable<System.DateTime> StartDate { get; set; }
public Nullable<System.DateTime> LastInspDate { get; set; }
public string Remarks { get; set; }
public Nullable<System.DateTime> NextInspDate { get; set; }
public Nullable<System.DateTime> IntermediateDue { get; set; }
public Nullable<System.DateTime> ThroughDue { get; set; }
public string DueDate { get; set; }
public string GroupStatusID { get; set; }
public Nullable<int> StatusID { get; set; }
public Nullable<int> EnggDataID { get; set; }
public string FunctionalLocation { get; set; }
public Nullable<System.DateTime> CreatedOn { get; set; }
public Nullable<int> CreatedBy { get; set; }
public Nullable<System.DateTime> ModifiedOn { get; set; }
public Nullable<int> ModifiedBy { get; set; }
public string PersonName { get; set; }
public string CostPerHour_Dollar { get; set; }
}
This is very simple, there's nothing that allows a list of PIRTaskList to be implicitly converted into a list of TasksList. The fact that the classes share the same properties names is irrelevant.
You have many options and which one you choose depends entirely on your project/team and knowledge you have about the system that we don't.
Use query.Select(x => new TasksList ...).ToList() to manually transform the items
Use an implicit/explicit conversion with a .Select
Use a library like AutoMapper
Use a List<dynamic>/List<object> (and lose type safety)
Probably more options that I cannot think of right now

How to map a mongodb entity to elasticsearch create index in c#?

I am trying to create an index for my project to elasticsearch.
following are my classes
public class Asset
{
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public AssetComponent Component { get; set; }
public AssetSite Site { get; set; }
public AssetComposition AssetComposition { get; set; }
public string SerialNumber { get; set; }
public string WorkOrderNumber { get; set; }
public AssetFigure Figure {get;set;}
public string SkuNumber { get; set; }
public Status AssetStatus { get; set; }
public Status InspectionStatus { get; set; }
public BsonDocument UserDefinedAttributes { get; set; }
public TimeAndUserTrail Trail { get; set; }
[BsonIgnoreIfDefault]
public List<Identifier> Identifiers { get; set; } = new List<Identifier>();
[BsonIgnoreIfDefault]
public List<Document> Documents { get; set; } = new List<Document>();
public Status OrderStatus { get; set; }
}
public class AssetComponent
{
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string Name { get; set; }
}
public class AssetSite
{
[BsonRepresentation(BsonType.ObjectId)]
public string LocationId { get; set; }
[BsonRepresentation(BsonType.ObjectId)]
public string SiteId { get; set; }
}
public class AssetComposition
{
public List<AssetComponentComposition> SubAssemblies { get; set; }
public List<AssetComponentComposition> Parts { get; set; }
public List<AssetComponentComposition> Accessories { get; set; }
}
public class AssetComponentComposition
{
public string Name { get; set; }
public string AssetType { get; set; }
public List<ObjectId> AssetIds { get; set; }
}
public class AssetFigure
{
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string Name { get; set; }
}
public class Status
{
public string Id { get; set; }
public string Value { get; set; }
}
And in elasticsearch create index method
var createIndexResponse = client.CreateIndex(indexName, c => c
.Mappings(ms => ms
.Map<Asset>(m => m
.AutoMap<AssetComposition>()
.AutoMap<AssetComponent>()
.AutoMap<AssetSite>()
.AutoMap<AssetFigure>()
.AutoMap<BsonDocument>()
.AutoMap<TimeAndUserTrail>()
.AutoMap<Core.Entities.Status>()
.AutoMap(typeof(AssetComponentComposition))
.AutoMap(typeof(Identifier))
.AutoMap(typeof(Document))
.AutoMap(typeof(ObjectId))
)
)
);
When I run this, I am getting the following exception.
System.Reflection.AmbiguousMatchException: 'Ambiguous match found.'
I tried to resolve this using the following link from elasticsearch official document
https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/auto-map.html
But again I didn't resolved the issue. Please help.
The problem is occurring due to the 'BsonDocument' which has inbuilt properties which need to be map to the elastic search mapping environment. After adding those additional fields the issue resolved

Map a class which inherits a list of objects to a similar class

In my project I need to map objects from the external systems to DTOs. The object I want to map is:
public class PriceLists : List<PriceList> { }
I get the idea of mapping properties within the class but having difficulty finding a solution for this case. My DTO will preferably be "identical" to this source class to make it as simple as possible for the moment:
public class PriceListsDTO : List<PriceListDTO> { }
Is there a simple solution or do I need to refactor my DTO object?
Thanks.
Edit: I have tried creating mapping for a list of Price lists without success regarding this problem.
Mapper.Initialize(cfg => { cfg.CreateMap<PriceList>, <PriceListDTO>(); });
Mapper.Initialize(cfg => { cfg.CreateMap<IList<PriceList>, IList<PriceListDTO>>(); });
Edit2:
public class PriceList
{
public string Agreement { get; set; }
public Currency Currency { get; set; }
public string Description { get; set; }
public Nullable<DateTime> EndDate { get; set; }
public int Id { get; set; }
public Nullable<Guid> ImageKey { get; set; }
public bool IsBid { get; set; }
public bool IsLimitedToStock { get; set; }
public bool IsPrimary { get; set; }
public bool IsPublic { get; set; }
public string Name { get; set; }
public Nullable<DateTime> StartDate { get; set; }
public int Type { get; set; }
}
public class PriceListDTO
{
public string Agreement { get; set; }
public CurrencyViewModel Currency { get; set; }
public string Description { get; set; }
public DateTime? EndDate { get; set; }
public int Id { get; set; }
public Guid? ImageKey { get; set; }
public bool IsBid { get; set; }
public bool IsLimitedToStock { get; set; }
public bool IsPrimary { get; set; }
public bool IsPublic { get; set; }
public string Name { get; set; }
public DateTime? StartDate { get; set; }
public int Type { get; set; }
}
And the Currency class and DTO only contains string properties.
From the code you've given, you never actually told AutoMapper to associate the DTO with the model class. If you call Initialize twice, the second will REMOVE any previous mappings. Try updating your configuration to do the following:
Mapper.Initialize( cfg => {
cfg.CreateMap<PriceList, PriceListDTO>()
.ReverseMap();
// Not sure if this is required if you already have the model/dto map
cfg.CreateMap<IList<PriceList>, IList<PriceListDTO>>();
cfg.AssertConfigurationIsValid();
});
public class PriceList
{
public string Agreement { get; set; }
public Currency Currency { get; set; }
public string Description { get; set; }
public Nullable<DateTime> EndDate { get; set; }
public int Id { get; set; }
public Nullable<Guid> ImageKey { get; set; }
public bool IsBid { get; set; }
public bool IsLimitedToStock { get; set; }
public bool IsPrimary { get; set; }
public bool IsPublic { get; set; }
public string Name { get; set; }
public Nullable<DateTime> StartDate { get; set; }
public int Type { get; set; }
}
public class PriceListDTO
{
public string Agreement { get; set; }
public Currency Currency { get; set; }
public string Description { get; set; }
public DateTime? EndDate { get; set; }
public int Id { get; set; }
public Guid? ImageKey { get; set; }
public bool IsBid { get; set; }
public bool IsLimitedToStock { get; set; }
public bool IsPrimary { get; set; }
public bool IsPublic { get; set; }
public string Name { get; set; }
public DateTime? StartDate { get; set; }
public int Type { get; set; }
}
after that try automapper.mapper.createmap it
will work for you otherwise you need to use formember method to map
properties of currency with currencyviewmodel one by one because
object are different to each other just try with it. hope it will help
for you . Thanks

JSON circular reference in asp mvc 5

I am getting an a Circular Reference Serialization Error and failed to load result...status of 500.
I'm trying to create a dynamic dropdown list with the options from the database, appending options with js.
those are my class:
public class IdentificacionViewModel
{ public virtual Causas Causas { get; set; }
public virtual Identificacion Idententificacion { get; set; }
}
public partial class Causas
{
public int Id { get; set; }
public string Causa { get; set; }
public string Agente { get; set; }
public Nullable<int> Id_Subproceso { get; set; }
public Nullable<int> Id_identificacion { get; set; }
public virtual Identificacion Identificacion { get; set; }
public virtual Subprocesos Subprocesos { get; set; }
}
public Identificacion()
{
this.Causas = new HashSet<Causas>();
}
public int Id { get; set; }
public string Nombre { get; set; }
public Nullable<int> Id_Servicio { get; set; }
public string Etapa { get; set; }
public string Riesgo { get; set; }
public string EfectoProb { get; set; }
public virtual ICollection<Causas> Causas { get; set; }
public virtual Servicios Servicios { get; set; }
public virtual Impacto Impacto { get; set; }
}
my controller is:
public ActionResult GetA()
{
var category = db.Causas.ToList();
return Json(category, JsonRequestBehavior.AllowGet);
}
i don't know what could be the problem and thanks for the help.
Lazy Loading of the Causas collection can be turned off by making the Causas property non-virtual
public ICollection<Causas> Causas { get; set; }
Loading of the Causas collection can still be achieved using eager loading
var Identification = context.Identificacion
.Include(b => b.Causas)
.ToList();

Why is my EF detaching not enough?

I try to detach an entity of type group.
Actucally I save it in my cache, and detach it a moment before responding the client.
On the next request I get the group from the cache and re-attch a new objectContext.
However I get An entity object cannot be referenced by multiple instances of IEntityChangeTracker
I know attach includes all related entities but detach doesn't. There I have to detach every related entity.
What am I missing in my detach?
here is my entities hirarchy:
public partial class App
{
public App()
{
this.Pairs = new HashSet<Pair>();
}
public string AppName { get; set; }
public System.Guid AppGuid { get; set; }
public string ClientAppID { get; set; }
public bool IsDeleted { get; set; }
public Nullable<System.DateTime> CreatedDate { get; set; }
public Nullable<System.DateTime> UpdatedDate { get; set; }
public virtual AppsData AppsData { get; set; }
public virtual ICollection<Pair> Pairs { get; set; }
}
public partial class AppsData
{
public System.Guid AppGuid { get; set; }
public string Url { get; set; }
public string DisplayName { get; set; }
public string AppDesc { get; set; }
public string PrivacyPolicyUrl { get; set; }
public string TermsOfUseUrl { get; set; }
public string LocalizationKey { get; set; }
public string Compatibility { get; set; }
public bool HiddenApp { get; set; }
public bool IsExperimental { get; set; }
public virtual App App { get; set; }
}
public partial class Browser
{
public Browser()
{
this.BrowserVersions = new HashSet<BrowserVersion>();
}
public int BrowserID { get; set; }
public string BrowserName { get; set; }
public string BrowserCode { get; set; }
public virtual ICollection<BrowserVersion> BrowserVersions { get; set; }
}
public partial class BrowserVersion
{
public BrowserVersion()
{
this.BrowserVerToCriterias = new HashSet<BrowserVerToCriteria>();
}
public System.Guid BrowserVersionID { get; set; }
public int BrowserID { get; set; }
public string Version { get; set; }
public System.DateTime CreatedDate { get; set; }
public System.DateTime UpdatedDate { get; set; }
public Nullable<int> Group_Id { get; set; }
public virtual Browser Browser { get; set; }
public virtual ICollection<BrowserVerToCriteria> BrowserVerToCriterias { get; set; }
}
public partial class BrowserVerToCriteria
{
public System.Guid CriteriaID { get; set; }
public System.Guid BrowserVersionID { get; set; }
public string ConditionBrowserVersion { get; set; }
public virtual BrowserVersion BrowserVersion { get; set; }
public virtual Criterion Criterion { get; set; }
}
public partial class CommonConfig
{
public int ID { get; set; }
public string NAME { get; set; }
public string VALUE { get; set; }
public System.DateTime CREATED_DATE { get; set; }
public System.DateTime UPDATED_DATE { get; set; }
public byte GROUP_ID { get; set; }
public string DESCRIPTION { get; set; }
}
public partial class Country
{
public Country()
{
this.Criteria = new HashSet<Criterion>();
this.Criteria1 = new HashSet<Criterion>();
}
public int CountryID { get; set; }
public string CountryCode { get; set; }
public string CountryName { get; set; }
public virtual ICollection<Criterion> Criteria { get; set; }
public virtual ICollection<Criterion> Criteria1 { get; set; }
}
public Criterion()
{
this.BrowserVerToCriterias = new HashSet<BrowserVerToCriteria>();
this.Countries = new HashSet<Country>();
this.CountriesExceptions = new HashSet<Country>();
this.Pairs = new HashSet<Pair>();
}
public System.Guid CriteriaID { get; set; }
public string Domains { get; set; }
public System.DateTime CreatedDate { get; set; }
public System.DateTime UpdatedDate { get; set; }
public string DomainsExclude { get; set; }
public virtual ICollection<BrowserVerToCriteria> BrowserVerToCriterias { get; set; }
public virtual ICollection<Country> Countries { get; set; }
public virtual ICollection<Country> CountriesExceptions { get; set; }
public virtual ICollection<Pair> Pairs { get; set; }
}
public partial class CTID
{
public string CTID1 { get; set; }
public string AppVersion { get; set; }
}
public partial class CtidPgPastExistence
{
public string Ctid { get; set; }
}
public partial class Group
{
public Group()
{
this.Pairs = new HashSet<Pair>();
}
public System.Guid GroupId { get; set; }
public int TestId { get; set; }
public int IdInTest { get; set; }
public bool WelcomeExperienceEnabledByDefault { get; set; }
public virtual MamConfiguration MamConfiguration { get; set; }
public virtual ICollection<Pair> Pairs { get; set; }
}
public partial class MamConfiguration
{
public MamConfiguration()
{
this.Groups = new HashSet<Group>();
this.MamConfigurationCTIDs = new HashSet<MamConfigurationCTID>();
}
public int TestID { get; set; }
public string TestName { get; set; }
public string Description { get; set; }
public int StatusId { get; set; }
public System.DateTime CreatedDate { get; set; }
public System.DateTime UpdatedDate { get; set; }
public bool IsProd { get; set; }
public int TestTraffic { get; set; }
public virtual ICollection<Group> Groups { get; set; }
public virtual MamConfigurationStatus MamConfigurationStatus { get; set; }
public virtual ICollection<MamConfigurationCTID> MamConfigurationCTIDs { get; set; }
}
public partial class MamConfigurationCTID
{
public int TestID { get; set; }
public string CTID { get; set; }
public virtual MamConfiguration MamConfiguration { get; set; }
}
public partial class MamConfigurationStatus
{
public MamConfigurationStatus()
{
this.MamConfigurations = new HashSet<MamConfiguration>();
}
public int StatusId { get; set; }
public string Status { get; set; }
public virtual ICollection<MamConfiguration> MamConfigurations { get; set; }
}
public partial class Pair
{
public Pair()
{
this.Groups = new HashSet<Group>();
}
public System.Guid PairID { get; set; }
public System.Guid CriteriaID { get; set; }
public System.Guid AppGuid { get; set; }
public virtual App App { get; set; }
public virtual Criterion Criterion { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}
public partial class SettingsServicesConfig
{
public int ID { get; set; }
public string Name { get; set; }
public string URL { get; set; }
public int Interval { get; set; }
public System.DateTime UPDATED_DATE { get; set; }
public System.DateTime CREATED_DATE { get; set; }
public int GROUP_ID { get; set; }
}
here is my detach function:
public void Detach<T>(MaMDBEntities maMdbEntities, T item) where T : class, new()
{
switch (typeof (T).Name.ToLower())
{
case "group":
{
var group = item as Group;
if (group == null)
{
mApplicationLogger.Error(string.Format("Couldn't cast item to type 'Group'"));
throw new InvalidCastException(string.Format("Couldn't cast item to type 'Group'"));
}
DetachState(maMdbEntities, group.MamConfiguration);
foreach (var pair in group.Pairs.ToList())
{
DetachState(maMdbEntities, pair.App);
DetachState(maMdbEntities, pair.App.AppsData);
foreach (var country in pair.Criterion.Countries.ToList())
{
DetachState(maMdbEntities, country);
}
foreach (var country in pair.Criterion.CountriesExceptions.ToList())
{
DetachState(maMdbEntities, country);
}
foreach (var browserVerToCriterias in pair.Criterion.BrowserVerToCriterias.ToList())
{
DetachState(maMdbEntities, browserVerToCriterias.BrowserVersion.Browser);
DetachState(maMdbEntities, browserVerToCriterias.BrowserVersion);
DetachState(maMdbEntities, browserVerToCriterias);
}
DetachState(maMdbEntities, pair.Criterion);
DetachState(maMdbEntities, pair);
}
break;
}
}
maMdbEntities.Entry(item).State = EntityState.Detached;
}
private static void DetachState(MaMDBEntities maMdbEntities, object item)
{
maMdbEntities.Entry(item).State = EntityState.Detached;
}
I believe that you need to make sure that none of the entities which remain in your context, reference any of those which have been detached. So if say, something else references a detached instance of Pair, the context will quite happily find it, traverse its navigation properties and add the whole lot back in.
Rather than setting the State property have you tried:
((IObjectContextAdapter)maMdbEntities).ObjectContext.Detach(item);
This is supposed to detach any links to the item being detached in addition to the item itself.
EDIT
Ok, lets look at the "detach any links to the item being detached ...", ObjectContext.Detach ultimately calls this method:
// System.Data.Objects.EntityEntry
internal void Detach()
{
base.ValidateState();
bool flag = false;
RelationshipManager relationshipManager = this._wrappedEntity.RelationshipManager;
flag = (base.State != EntityState.Added && this.IsOneEndOfSomeRelationship());
this._cache.TransactionManager.BeginDetaching();
try
{
relationshipManager.DetachEntityFromRelationships(base.State);
}
finally
{
this._cache.TransactionManager.EndDetaching();
}
this.DetachRelationshipsEntries(relationshipManager);
IEntityWrapper wrappedEntity = this._wrappedEntity;
EntityKey entityKey = this._entityKey;
EntityState state = base.State;
if (flag)
{
this.DegradeEntry();
}
else
{
this._wrappedEntity.ObjectStateEntry = null;
this._cache.ChangeState(this, base.State, EntityState.Detached);
}
if (state != EntityState.Added)
{
wrappedEntity.EntityKey = entityKey;
}
}
DetachEntityFromRelationships breaking down all the links.
The documentation on ObjectContext.Detach is not specific about the tearing down of links http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.detach.aspx it does say "After the Detach method is called, the system will no longer keep references that point to this object and it can be collected by the garbage collector", which implies all LinkDescriptors will also have been removed.
With regards your 3rd comment "Do you think IObjectContextAdapter will enable full detachment. Or there will always be other object in context that I will misss and not detach?" there are two things here; there is the property of the object and the LinkDescriptor which the context uses to track to the relationship. Detach merely stops tracking an object's relationships by detaching the LinkDescriptors, it doesn't detach the object at the other end of the relationship. Neither does it set such properties to null, if you inspect the object after detaching it will still have those properties set.
Is this the best approach? Detaching and reattaching is difficult to get right. If you need to detach and reattach I would suggest you move your deep detach rountines into the classes themselves rather than in a generic method.
That said, you wrote "On the next request I get the group from the cache..." which leads to me wonder what would be the longest period of time between two requests? Could you be introducing concurrency issues by caching? Are you hosting your WCF service in IIS? Could you use IIS's caching if concurrency will not be a problem? Are you handling all requests on the same thread? You might not be aware that ObjectContext instance methods are not thread safe.

Categories

Resources