I'm trying to read Mappings from another project, by loading the Assemblies, instantiating the Context Types and getting their MetadataWorkspace through the IObjectContextAdapter.ObjectContext .
My code works for regular contexts just fine, but I have a few contexts which map to Views, not Tables, and every time I try to get the MetadataWorkspace an Exception is thrown : EntityType 'ExampleEntityMappedToView' has no key defined. Define the key for this Entity Type.
I looked it up in my code and there's definetly a Primary key defined through HasKey(t => t.PrimaryKeyId);. Then again, as far as I can tell Views can not have primary keys in the first place in TSql ?
Is this a known limitation or is there something I need to do in the Mapping to make it valid?
Related
It's not completely clear to me what's the diference between using AsNoTracking() on a entity that has a key, and using HasNoKey(). As I understand, when using AsNoTracking(), even though the changetracker does not track changes on the resulting objects, the objects are still kept in the DbContext's memory. If you try to Attach a new object with the same key as one already in memory, you get an error. (correct me if i'm wrong).
So is the behavior the same if you use HasNoKey (former DbQuery<>)?
Introducing ModelBuilder.Entity<>().HasNoKey() is one of the breaking changes in EF Core 3.0 as stated:
A query type now becomes just an entity type without a primary key. Keyless entity types have the same functionality as query types in previous versions.
Query types were a means to query data that doesn't define a primary key in a structured way. That is, a query type was used for mapping entity types without keys (more likely from a view, but possibly from a table) while a regular entity type was used when a key was available (more likely from a table, but possibly from a view).
You said that:
If you try to Attach a new object with the same key as one already in memory, you get an error. (correct me if i'm wrong). So is the behavior the same if you use HasNoKey (former DbQuery<>)?
-Tracking in EF Core transaction are based on Entity Primary key. As the above documentation clearly stating that EntityType with .HasNoKey() is QueryType which does not have any key defined. So tracking is completely void in case of EntityType with HasNoKey().
For more details : Query types are consolidated with entity types
I'm using Entity Framework 5, code first approach. As there's no built in support for updating child entities in disconnected scenario, I'm building my own mechanism to do that. At some point I need to get the property of an entity with which it has a Foreign Key relationship with another (principal) entity. I've tried to get access to CSpace through
((IObjectContextAdapter)dbContext).ObjectContext.MetadataWorkspace.GetItems<MyEntity>(System.Data.Entity.Core.Metadata.Edm.DataSpace.CSpace)
but here I got a warning that said there's no implicit conversion between MyEntity and System.Data.Entity.Core.Metadata.Edm.GlobalItem.
I can't look for a property that has Foreign Key attribute because in most of my entities I use EF convention to get foreign keys automatically. So how one would go about finding which property is used for foreign key relationship.
Thanks to #octavioccl's post I was able to do what I want. So I was in the right path to look inside ObjectContext.
Using EF with MVC4 allows you to specify the inclusion of Foreign Key columns in the model. While this not normally part of OR modeling, it does allow MVC4 to automatically generate views with dropdown lists, for the foreign key relationships, when you generate a controller with the MVC controller with read/write actions and views, using Entity Framework option.
I have hit a problem creating an object in this scenario.
Greatly simplified, the models in question are:
Questionnaire:
QuestionnaireID: PK
CandidateId: FK
Candidate: Associated object
Candidate:
CandidateID: PK
Name: string
The problem I have hit is that on a Create view post-back to create a new Questionnaire ModelState.IsValid is false. On investigation the error listed is The parameter conversion from type 'System.String' to type 'Data.Candidate' failed because no type converter can convert between these types.
ModelState.Keys includes Questionnaire.Candidate as well as Questionnaire.CandidateId (which is valid).
I am sure this is something simple, but would like to hear some solutions. The viewbag only has a set for the drop-down list and the view has an #model of type #model Data.Questionnaire. There are no editor fields bound to Questionnaire.Candidate..
As I have no idea why the built-in EF models do not like the MVC generated scaffolding, for Create postbacks with foreign key columns enabled, I have reverted to what is a more secure solution (still happy to hear why it fails out-of-the-box):
Create individual view models for specific sensitive operations like create
The theory goes that there are a number of problems using EF domain entities as viewmodels including:
They potentially expose too much information or allow additional fields to be posted back
Validation text is an interface concern and should not be part of a the data model (they actually suggest even the viewmodel is not the place for this text, but I digress).
So basically I now have a CreateCandidateQuestionnaireVM class with only the required fields for selecting appropriate values for a new instance.
I'm migrating from Linq-to-SQL to Entity Framework (4.4), using Database First with a DbContext. I'm wondering whether the following behavior is normal:
using (var e = new AgendaEntities()) {
var store = e.Stores.First();
var office = e.Offices.Create();
office.Store = store; // Set association
Console.WriteLine(office.StoreID); // shows Guid.Empty, expected store.ID!
}
In L2S, setting the Store association to an entity would also update the StoreID key. In EF, this doesn't seem to be happening. This is regardless of whether the entities are new or loaded from the context.
When I SaveChanges, it saves correctly and the StoreID is updated to match office.ID, but why does this only happen after the save?
Is there something I'm missing, or am I now supposed to keep foreign keys in sync manually?
Solution Edit:
This is called property fixup, and used to be done automatically by the generated proxies. However, with DbContext this is no longer the case. According to this Connect issue, this is by design.
Hello,
The DbContext template actually doesn't generate classes that will be used as change tracking proxies - just lazy loading proxies (which don't do fix-up). We made this decision because change tracking proxies are complex and have a lot of nuances that can be very confusing to developers.
If you want fix-up to occur before SaveChanges you can call myContext.ChangeTracker.DetectChanges.
~EF Team
An alternative is to call DbContext.Entry(entity), which will sync up the entity. This is described in this article: Relationships and Navigation Properties under "Synchronizing the changes between the FKs and Navigation properties"
No. Entity framework does this for you. Read Relationships and Navigation Properties for more information.
By assigning a new object to a navigation property. The following
code creates a relationship between a course and a department.
If the objects are attached to the context, the course is also
added to the department.Courses collection, and the
corresponding foreign key property on the course object is set to the
key property value of the department.
course.Department = department;
But as you observed, this only happens after you call SaveChanges or one of the other actions mentioned in the "Synchronizing the changes between the FKs and Navigation properties" portion of the document linked above.
If you are using POCO entities without proxies, you must make sure
that the DetectChanges method is called to synchronize the related
objects in the context. Note, that the following APIs automatically
trigger a DetectChanges call.
DbSet.Add
DbSet.Find
DbSet.Remove
DbSet.Local
DbContext.SaveChanges
DbSet.Attach
DbContext.GetValidationErrors
DbContext.Entry
DbChangeTracker.Entries
Executing a LINQ query against a DbSet
If this is not happening at all, my guess is that you haven't properly defined StoreID as the foreign key of the navigation property Store.
For part of the project I'm currently working on, I have a set of four tables for syndicatable actions. One table is the abstract base for the other three, and each table is represented in my EF model like so:
EF Model -- Actions http://chris.charabaruk.com/system/files/images/EF+Model+Actions.png
There are two problems that I'm currently facing with this, however. The first problem is that Actor (a reference to a User) and Subject (a reference to an entity of the class associated with each type of action) are null in my subclasses, despite the associated database columns holding valid keys to rows in their associated tables. While I can get the keys via ActorReference and SubjectReference this of course requires setting up a new EF context and querying it for the referenced objects (as FooReference.Value is also null).
The second problem is that the reciprocal end of the relationship between the concrete action classes and their related entity classes always turn up nothing. For example, Task.RelatedActions, which should give me all TaskAction objects where Subject refers to the particular task object on which RelatedActions is called, is entirely devoid of objects. Again, valid rows exist in the database, Entity Framework just isn't putting them in objects and handing them to me.
Anyone know what it is I'm doing wrong, and what I should do to make it work?
Update: Seems that none of the relationship properties are working in my entity model any more, at all. WTF...
I think the issue you are experiencing here is that by default the EF does not automatically load related entities. If you load an entity, the collection or reference to related entities will be empty unless you do one of the following things:
1) Use eager loading in order to retrieve your main entity and your related entity in a single query. To do this, modify your query by adding a call to the Include method. In your sample above, you might use the following query:
from a in context.Actions.Include("Actor") select a
This would retrieve each of the actions with the related Actor method.
2) Use explicit lazy loading to retrieve the related entity when you need it:
action1.ActorReference.Load()
In the version of the EF which will ship with .Net 4.0, you will also have the following additional option:
3) Turn on implicit lazy loading so that related entities will automatically be retrieved when you reference the navigation property.
Danny