Web Api Entity Framework - entity-framework

I've an error: "ExceptionMessage": "Self referencing loop detected for property 'Posto' with type 'UfficioServer.Posto'. Path '[0].Dipendente[0]'.",
when i call my web api, i need a list of Posti whit the association with Dipendente...
public List<Posto> GetAllPosti()
{
try
{
List<Posto> p = new List<Posto>();
UfficioPostiEntities1 db = new UfficioPostiEntities1();
db.Configuration.ProxyCreationEnabled = false;
var posto = db.Posto.Include("Dipendente").ToList();
var x = db.Posto.ToList();
return x;
}
can someone help me?

To avoid this error you should add the following to the Application_Start in Global.asax:
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter
.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
This is because (as per documentation)
ReferenceLoopHandling.Ignore: Json.NET will ignore objects in
reference loops and not serialize them. The first time an object is
encountered it will be serialized as usual but if the object is
encountered as a child object of itself the serializer will skip
serializing it.

Related

Entity Framework Z Plus Batch Update

I am using Entity Framework Z Plus Batch Update method. I am unable to proceed due to below issue. Actually Update method works good when i give static values like tagName="amir1". But I need to get the Tagdescription from a web service or from another collection based on the tagId, Update method is not accepting a extension method or any other method to accomplish my requirement.Its saying
"LINQ to Entities does not recognize the method 'System.String GetTagDescription(Int32)' method, and this method cannot be translated into a store expression.".
Hope my requirement is clear now. Please guide me if there is any other approach for my requirement.
Here is my code:
using (var context = new TrialsDBEntities())
{
context.tblTags.Where(x => (tagIdCollection.Contains(x.tagId))).
Update(m => new tblTag { tagDescription = m.tagId.GetTagDescription(), tagName = "amir1" });
}
public static string GetTagDescription(this int i)
{
return "test" + i;
///Replace above line with call to database or web service call
getting some text by giving i as input
}
Disclaimer: I'm the owner of the project Entity Framework Plus
Unfortunately, that's not possible to use BatchUpdate with a value that changes from a row to another.
Disclaimer: I'm the owner of the project Entity Framework Extensions
In this situation, we normally recommend using our paid library that's build for this kind of situation and offer high-performance saving operation.
Example
// Easiest way
context.BulkSaveChanges();
// Fastest way
context.BulkUpdate(tags);
EDIT: Answer comment
If I can't use updated row so why the signature of action is misleading and give me possibility to write like this: e => new Entity { Name = e.Name + "Edited" }
For most providers such as SQL Server, your expression is supported. You give a global expression so we can apply. Your expression doesn't doesn't change from a row to another, it's the same expression.
What is not supported is giving a specific expression from a row to another.
Write your code as follows:
using (var context = new TrialsDBEntities())
{
var tagsToBeUpdated = context.tblTags.Where(x => (tagIdCollection.Contains(x.tagId))).AsNoTracking().ToList();
//Only use this code block if your tagsToBeUpdated list is too large
Parallel.ForEach(tagsToBeUpdated, tagToBeUpdated =>
{
var tagDescription = GetTagDescription(tagToBeUpdated.tagId);
tagToBeUpdated.tagDescription = tagDescription;
context.Entry(tagToBeUpdated).State = EntityState.Modified;
});
//Only use this code block if your tagsToBeUpdated list is not too large
foreach(var tagToBeUpdated in tagsToBeUpdated)
{
var tagDescription = GetTagDescription(tagToBeUpdated.tagId);
tagToBeUpdated.tagDescription = tagDescription;
context.Entry(tagToBeUpdated).State = EntityState.Modified;
}
context.SaveChanges();
}
public static string GetTagDescription(int i)
{
return "test" + i;
///Replace above line with call to database or web service call
//getting some text by giving i as input
}

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection

I'm having trouble with one of my queries because of EF's change tracking and lazy loading features. The thing is that after I'm getting the result of the query, I'm using AutoMapper to map the domain objects into my business model but it keeps throwing an exception because the context has been disposed.
The ObjectContext instance has been disposed and can no longer be used
for operations that require a connection.
When I look at the resultant collection in the debugger, I see that it is a list of DynamicProxy and not the actual entity. I tried to stop Change Tracking but that did not help. Here's my code:
public List<ContentTypeColumn> GetContentTypeColumns(Int64 contentTypeId)
{
List<ContentTypeColumn> result = new List<ContentTypeColumn>();
using (SCGREDbContext context = new SCGREDbContext())
{
ContentType contentType = context.ContentTypes.Include("Parent").AsNoTracking().FirstOrDefault(x => x.Id.Equals(contentTypeId));
result.AddRange(contentType.ContentTypeColumns.ToList());
while (contentType.Parent != null)
{
result.AddRange(contentType.Parent.ContentTypeColumns.ToList());
contentType = contentType.Parent;
}
}
return result.ToList();
}
Note: If you need to look into my domain model involved in this operation you can refer to this question.
If you need to stop lazy loading and dynamic change tracking you can simply turn it off:
using (SCGREDbContext context = new SCGREDbContext())
{
context.Configuration.ProxyCreationEnabled = false;
...
}

EF4: ObjectSet.AddObject() not working

I am setting up a repository with Entity Framework 4, and I can't get the ObjectSet.AddObject() method working. Here is the code I am using--to keep things simple, I copied it out of the repository into my unit test method:
/* m_FilePath value is passed in by test initializer. */
// Configure a SQL CE connection string
var sqlCompactConnectionString = string.Format("Data Source={0}", m_FilePath);
// Create an Entity Connection String Builder
var builder = new EntityConnectionStringBuilder();
builder.Metadata = string.Format("res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl", "Model.Notes");
builder.Provider = "System.Data.SqlServerCe.4.0";
builder.ProviderConnectionString = sqlCompactConnectionString;
var edmConnectionString = builder.ToString();
// Create object context and object set
var context = new NotesContainer(edmConnectionString);
var objectSet = context.CreateObjectSet<Note>();
// Add a note
var entity = new Note();
objectSet.AddObject(entity);
// Build assertion
var notes = objectSet.AsEnumerable();
var count = notes.Count();
Assert.AreEqual(1, count);
The count that is returned is zero--the object set is empty, so the assertion fails. When I step through the code, the object context and object set are created, but enumeration of the object set returns no results.
What's the error in my code? Thanks for your help.
The notes.Count() is executed against your data file (which I assume is empty). Your new object won't be added until you call context.SaveChanges().
Consider:
objectSet.AddObject(new Note()); // new object present in memory
var notes = objectSet.AsEnumerable();
var count = notes.Count(); // query against DB file;
// what's in memory at this point is irrelevant
Add context.SaveChanges() after you add new Note and assert will pass. But of course, that introduces whole new range of problems with keeping DB state the same for every test run.
That is not entirely true.
e.g. Parent / Childs
When using Context.AddObject() for Parent it won't be added to until Context.SaveChanges() is called but when adding a Child it will be added without saving (when foreign keys are set of course).
Not sure if it is a bug or if it is by design in the EF ...
The only "workaround" I see at the moment:
introduce a Client table and each object (Parent, Child) has a reference to a Client
call context.SaveChanges() (Drawback: the user has no chance to cancel the operation)
Also calling Context.ParentSet.Execute(MergeOption.AppendOnly); does not have the expected effect!
Solution/Workaround: I maintain my own list of objects for adding/removing + setting the DataSource = null and then to my internal list.
Since it is necessary to set the DataSource = null it seems that there is something strange in EF ...

IronPython and Entity Framework

Possibly really simple question, but I'm new to IronPython. I would like use IronPython to crawl an entity I pass to it, but when I try to use any extension methods, it, as sort of expected, blows up. How do I traverse my POCOs in IronPython?
delegate bool EvaluateRule(MyEntity entity);
//Keep in mind this is just to test, no actual value provided
string expression = #"entity.Flags.FirstOrDefault() == null";
MyEntity entity = new MyEntity();
PythonEngine engine = new PythonEngine();
EvaluateRule rule = engine.CreateLambda<EvaluateRule>(expression);
bool result = rule.Invoke(entity);
I get the following: 'EntityCollection[MyEntity]' object has no attribute 'FirstOrDefault'
Thanks in advance!
You can call the extension methods as regular static methods:
string expression = #"Enumerable.FirstOrDefault(entity.Flags) == null";

EF 4.0 Dynamic Proxies POCO Object Does not match target type

I am using EF 4.0 and POCO's. I stumbled across this error while inserting to records into the data base.
Property accessor 'QualityReasonID' on object 'BI.Entities.QualityReason' threw the following exception:'Object does not match target type.'
There errors occur on the Databind to a GridView after saving a new record to the database. I identified what is happening but I am not sure WHY it is occurring or If I am using EF/POCO's incorrectly. Any insight would be appreciated.
The exception is occuring because the object types in the IEnumerable are not the same.
The orginal entrys in the table are of type System.Data.Entity.DynamicProxies.QualityReason_E483AD567288B459706092F1825F53B1F93C65C5329F8095DD1D848B5D039F04}
While the new one is BI.Entities.QuailtyReason.
Here is how I insert the new object.
public void createQualityReason(QualityReason qReasons)
{
dbcontext.QualityReasons.AddObject(qReasons);
dbcontext.SaveChanges();
}
I resolved the error by changing the fetch code from:
public IEnumerable<QualityReason> fetchQualityReasons()
{
IEnumerable<QualityReason> queryReasons = dbcontext.QualityReasons.AsEnumerable();
return queryReasons;
}
to
public IEnumerable<QualityReason> fetchQualityReasons()
{
IEnumerable<QualityReason> queryReasons = from data in dbcontext.QualityReasons.AsEnumerable()
select new QualityReason
{
QualityReasonID = data.QualityReasonID,
QualityReasonName = data.QualityReasonName
};
return queryReasons;
}
So to get around the error I have to select into the POCO class explicitly each time. This feels like I am going something wrong. Any thoughts?
The error is caused because GridView does not handle polymorphic datasources when using boundfields. So you have two options
Use TemplateFields instead which can handle polymorphic datasources, this may changing some of your front end code and GridView events.
Use Linq to create a non-polymorphic databsource that the boundfields can handle
So instead of using something like ti
gvGroups.DataSource = ProductHelper.Get()
gvGroups.DataBind();
var query = from p in ProductHelper.Get()
select new {p.ProductId, p.ProductName, p.ProductDesc, p.ProductLink};
gvGroups.DataSource = query;
gvGroups.DataBind();
I don't know if the problem has been solved yet, but I've had the same problem with my (POCO) "Scenario" class.
The problem disappeared when using a context.CreateObject<Scenario> to create the (POCO) object i.s.o. a .... = new Scenario().
Faced the same issue today and used Value Injecter to solve it. It's as simple as:
var dynamicProxyMember = _repository.FindOne<Member>(m=>m.Id = 1);
var member = new Member().InjectFrom(dynamicProxyMember) as Member;
That's it :)