I'm currently investigating the possibility to use table splitting with EF to stop pulling too many columns for nothing. As for now, I'm able to create a new entity, cut/paste the fields into the sub-entity and map it without much problems.
However, if one of those fields is a FK in the master table, it gives me the following error
"Running transformation: There is no property with name 'IdDocumentImportSource' defined in type referred by Role 'DocumentImports'."
I do understand that the both tables have a NavigationProperties that cannot be resolved anymore by the association FK because the field has been moved to the child table.
Here's my question; Is there a way to automaticaly move the association FK to the child table? I could only make it work by manually deleting the association, both navigation properties, creation the association FK of the child. It involves quite a lot of work on my part if I have to do all this manually for every association FK I got...!
DocumentImports is the ParentTable that I splitted into a new child table DocumentImports_StatusDetail and DocumentImportSources is the table being referenced by the FK.
Thanks!
Related
I'm having a problem in which the deletion of a record in a table works, but only so long as the table has no child foreign key relationships. Now, when we have a parent table and want to delete the record using EF, it fails with an error of, "The relationship could not be changed because one or more of the foreign-key properties is non-nullable." I've deleted cascading delete on the child table referencing the parent table. I've tested it within SSMS. It works fine. But from within C# it fails. We have a view model where we've defined a generic DeleteRow method. This works great, so long as the row being deleted has no child tables. It fails, if the table is a parent table. I tried looking here on Stackoverflow for an answer and came across this question, now closed: stackoverflow.com/questions/17723276/delete-a-single-record-from-entity-framework. The answer to this question used a discrete table in EF. We're using generics. Here's our code:
public void DeleteRow(T row)
{
if (App.MainDataContext != null && row != null)
{
App.MainDataContext.Entry<T>(row).State = EntityState.Deleted;
App.MainDataContext.SaveChanges();
}
}
I don't believe setting the State property to the enumeration EntityState.Deleted is working, as that's only setting it for the record in the parent table, not for any of the related records in the child tables. (MainDataContext is entity from a .EDMX file.) How do we delete a single record from any table using EF 6 when we're using generics to pass in the table type?
The problem is that when you set the state to deleted, the related entity is also loaded (tracked by the context's change tracker). When you delete your row, EF tries to set the parent navigation property to null, but it is a not nullable relationship.
To solve this you have to set a cascading delete in the relationship in you model (EDMX), not only in the database.
It should work also, if by the instance of your context the related entity is not tracked. In this case on SQL-Server side the cascading delete should work.
I use code first of Entity framework. There are two classes "Question" and "User". I defined a relationship as below:
this.HasRequired(v => v.Creator).WithMany(v => v.Questiones)
.HasForeignKey(v => v.CreatorId).WillCascadeOnDelete(false);
After gernerating the database I found that it always create foreign key between Id of User and CreatorId of Question. Because of lower performance of FK(and other reason),I want to define navigation property relationship without setting foreign key in database? Delete FK after EF created it?
If cannot do this using fluent api, could you tell me why EF designed in this way please?
About the lower performance of FK. I have a User table with 5 Million records in it. when I insert a Question into db, since the db check the question.CreatorId validation from User table, it always slower than without FK.
And there are many other reasons that I need to remove FK.
I think I am somewhat obsession because I think that deleting FK after created it is strangely and ugly. What i want is implementing this by using something like WithoutForeignKey in fluent api:
this.HasRequired(v => v.Creator).WithMany(v => v.Questiones)
.WithoutForeignKey(v => v.CreatorId).WillCascadeOnDelete(false);
Without questioning why are you trying to do this strange thing and going just to the answer: you could delete fk constraint after generated, or you could use migrations and remove FK generation from the migration code.
SQL code generated when traversing nav properties will work even if fk constraint doesn't exist, except for cascade deleting
If you want a relationship between two tables, you need to define a foreign key. No way around it. Even if you use Map() in fluent api, you can only hide the foreign key in your model, in the background EF will still use it and it will exist in the database.
Also I don't get what you mean by "performance" of foreign key? One extra (likely small) column won't make a difference. If you mean the navigation properties for the performance part, you can do 3 things:
Don't include them in your model
Make them non-virtual to disable lazy loading
Disable lazy loading all together with ctx.Configuration.LazyLoadingEnabled = false;
If you don't want to tell db about relation and treat both entities as not related (I wonder why), then just ignore these navigation properties and FK field. Note that you will be responsible for managing related entities: saving and loading them from db, updating ids etc
this.Ignore(q => q.Creator);
this.Ignore(q => q.CreatorId);
And you also need to ignore other side of relation, otherwise EF will generate FK column with default name Creator_CreatorId. So in Creator entity configuration:
this.Ignore(c => c.Questiones);
I have a bidirectional one to many relationship defined with cascade="all" defined on both ends in the mapping and inverse="true" on the one-to-many end.
When I call SaveOrUpdate a new entity the it correctly inserts a row into the parent table, then inserts all the child objects in the child table.
However, if I have an existing entity and update some properties of the child objects (say alter some string properties) then call SaveOrUpdate on the parent entity, it only updates the information in the parent table. I was expecting it to update all the child entities also.
Is this the expected behaviour? Do I need to manually update all the child objects myself? I'm not sure if I've messed something up in my mappings (in which case I'll add them to the question) or if this is how NHibernate is supposed to behave.
Edit: found the error; problem exists between keyboard and chair as usual.
Never mind, I was just being stupid and updating a property that isn't mapped to any columns.
Looks like NH will update child records that need updating only.
Pardon the massive headline.
I'm in the situation of having to build an application on top of a database, that I cannot make any changes to. The database does not have any primary- or foreignkeys set.
I'm using linq-2-sql, and I'm interested in having some properties exposed on the entities generated from my dbml. For instance, in the hypothetical example of a one-to-many relationship between table education and student - where each student record has a reference to an education id, I'd like to be able to go:
var student = GetAStudentFromContextOrWhatever();
var studentsEducation = student.Education;
It is my experience, that this kind of property is automatically generated when I drag'n'drop tables with foreignkey relationships from the server explorer.
However as previously mentioned, in this case I do not have these foreign key relationships - rather I am adding the relationships manually in the dbml file, specifying parent and child class.
When I add these relationships, I expect the involved entities in the designer.cs of my context to get populated with properties of a kind like those described above.
This, however, does not happen.
What must I do for my dbml to create these properties for me - based on these manually mapped associations between entities/tables that, on a database level, do not have foreign key associations?
Cheers!
L2S is just that Linq-to-SQL. If it isn't in SQL it won't be generated. The expression trees behind L2S just can't understand what you are doing. The place for your association is in a partial class file which you will have create manually. Also it probably won't update or insert through the association.
I know this is a very old question, but I just ran into the same problem. In order for the relationship in the DBML designer to automatically create the association properties for you, you need to have primary keys on your objects. If you click the column name in the designer, you'll see that your PK field has PrimaryKey = false. Switch that to True and build; all should be well.
Patrick
If I have a table with two foreign key fields to another table, I.E.
Table: User
Field: FK_PrimaryItem_ID
Field: FK_SecondaryItem_ID
Table: Item
Field: ItemID
When I'm using the entity framework, the generated objects become:
User.Item
and
User.Item1
and I can't differentiate between the two of them. I can map back to the name of the foreign key, but this is a difficult way to go about it. How can I find out which one, Item1 or Item is which field?
I would like to leave my EDMX file auto generating if possible.
I've not found any problems with updating my model once I'd changed the name of the Navigation Properties on the design surface.
In general, User.Item would be represent the first column the model came to with that foreign key, and User.Item1 would represent the second column.
But as I said, I just went into the model, and changed the name of the Navigation Properties to more usable names based on the association listed in the Mapping Details.
I had the same problem with a self-referencing key:
PageID
Parent_PageID (refers to PageID)
Until I renamed the Navigation Properties to "Parent" and "Children" respectively. The toughest part was figuring out which is which, which I did by noting the Multiplicity property on the NavigationProperty objects (0..1 for parent, * for children)