I have a multi-client DB (multitennant) with several tables.
Two of these tables are tblEmployees and tblTitles.
Now I have a relationship from tblEmployees.empTitle to tblTitles.ttlID.
That far everything is working.
But now I have to make the application for multiple clients/tennants.
So I added the fields tblEmployees.empClient and tblTitles.ttlClient and included them into the association.
This works fine for reading and for setting the persons title as well.
But if I try to remove the title (set it to NULL), SQL to Linq tries to modify both tblEmployees.empTitle and tblEmployees.empClient with is not allowed because tblEmployees.empClient is part of the primary key.
And so I get the following error:
InvalidOperationException:
An attempt was made to remove a relationship between a AppTitle and a AppEmployee.
However, one of the relationship's foreign keys (AppEmployee.clientID, AppEmployee.titleID) cannot be set to null.
How can I tell SQL to Linq only to modify field tblEmployees.empTitle???
I just solved the problem as everyone else did:
I let LinqToSQL think, clientID was not part of the primary key and removed it from the association.
However I did not modify the database, so the database still enforces to use a title of the same client/tennant.
Related
We are migrating a Microsoft Access application that has an SQL Server Back End to VB.NET for the frontend, and using LINQ to SQL. Most of the tables do not have a foreign key relationship on the database level, and the relationships are handled in code. Most of this works fine, but I am having trouble with times when the value to go into the foreign key doesn't actually exist.
In the small sample data set I created below to illustrate my problem, the Orders table is related to the Suppliers table through the SupplierID field in the Orders Table. I created a OneToMany association with the Suppliers as the Parent, and the Orders as the Child. This gives me a Supplier.Orders list, and an Order.Supplier property which is GREAT!
In my records the SupplierID in the Orders would be SupplierID from the Suppliers table, but there are a few 'magic values'. In this example 0 = No Supplier Exists, and -1 = TBD.
Any suggestions on how to best handle this?
I've handled this a few ways in the code so far, and none of them seem to be great:
I can manually set the Order.SupplierID property to 0 or -1, but I can only do that if I haven't already touched the Order.Supplier property. If I've already done something that makes LINQ use that association, it throws a foreign key error if I try to set the ID to something that doesn't exist.
I can set the value bypassing the LINQ by making an SQL statement(ie: dc.Connection.CreateCommand) but now I'm no longer working within the LINQ layer
I could make those 'magic IDs' actually exist, but from an architecture standpoint that feels wrong, since 'No Supplier' and 'TBD' are not actually suppliers. I would then also need to adjust anywhere that I show a list of the real Suppliers to not show those items.
I'm having trouble articulating my question well, so I apologize in advance.
This isn't the actual table structure/situation I'm dealing with, but I think it was a simpler way to demonstrate.
I have a Code-First .Net Core project using Entity Framework Core (2.0).
There are two tables, RhythmBlock and RhythmPattern.
Based on a List<RhythmBlock> property on RhythmPattern, EF created a column on RhythmBlock of RhythmPatternId, which I didn't really want.
So I tried all the following:
Mark the List<RhythmBlock> with the Annotation [NotMapped] and update db.
User FluentAPI to tell the db to Ignore and update db.
Delete the List<RhythmBlock> and replace with a method that returns the same, updated db.
All sorts of shenanigans with resetting the Migrations, direct sql, etc.
The results of all my attempts were that anytime I deleted the column RhythmPatternId in table RhythmBlocks, I would get the error Invalid Column Name. Even if the column and all indexes and foreign keys were deleted, all reference removed from the project, the error would continue.
The only way to get my project running again? Add back in the deleted column. So it's working, but I don't understand why?
I've deploy my database through ADO.net Entity Data Model by executing its diagram output query against my pre-made online database.
My database contains Only Lightswitch supported relations, One-Many, ZeroOne-Many & One-ZeroOne.
Finally, Attaching my database to my Lightswitch application as an external database and I was shocked by its result.
Lightswitch converts ALL One-ZeroOne relations to One-Many relations!
I suspect everything, retry tens of times trying to figure this strange issue out with no good news!
Question:
Why Lightswitch converts ALL One-ZeroOne relations to One-Many relations? Inconsistency!
Unless this is a bug, it would depend on the nullablility of your PK/FK. LightSwitch will not allow 0-1 for any key property that is not nullable.
Finally, I've solved it by a brute-force-like trials :S
Solution : ( Please don't ask me a WHY question as IDK will be my answer )
After adding a One-to-ZeroOne Relation you might have one or two Navigation Properties added to associated tables, but
You MUST add a Foreign Key as Scalar Property to the ZeroOne Table with Same type & true Nullable properties.
You MUST adjust the Residential Constrain for the association by double clicking the association line itself and make the FK in the ZeroOne Table dependent on the One table Key.
Generate the database script, execute it and Don't Update LightSwitch data source, Delete data source & Attach it again instead as it won't update relations correctly!
I'm trying to use EF to model an existing SQL database. The DB is multi-tenant by having a clientID column in every single table (I cannot change this). I have table structure like the following.
Table 'ItemID' columns:
ClientID (pk)
ItemID (pk)
ItemName
Table 'Items' columns:
ClientID (PK)
ItemID (PK) [FK to ItemID.ItemID]
Version (PK)
ItemAttribute1
ItemAttribute2
ItemAttribute3
The DB is designed to store previous versions (rows) of the 'Item' object, hence the 'Version' column and PK.
I am new to the EF and trying to adopt it for my project. However, it seems that EF cannot handle this situation very well. I am open to all ideas including using stored procedures or views instead of access tables directly from EF. What about getting rid of the PKs and using 'independant' relations instead?
One specific problem I ran into is that EF (at least the designer) requires all PKs in one table be mapped to all PK columns in any related table. This does not make sense to me, as the example I've given will never work given that constraint. I am trying to make Items inherit from ItemID. The error I get is:
Error 3003: Problem in mapping
fragments starting at line 170:All the
key properties (ItemID.ClientID,
ItemID.ItemID) of the EntitySet ItemID
must be mapped to all the key
properties (Items.ClientID,
Items.ItemID, Items.Version) of table
Items.
I have been looking up all I can find on this topic and nothing has answered these questions for me. I appreciate any help. Thanks.
The error that you are getting from your EDM is coming from the fact that EF supports inheritance only if both entities have the exact same primary keys (hence a one to one relationship on database) so you cannot have inheritance between these 2 entities according to the current schema.
However, I don't see a problem on having a One to Many association between ItemID and Items entities and I believe this is the default EF behavior when you update your model from the database.
Please have a look at this post for more info:
Entity Framework, TPT Inheritance
I have a SQL Server as backend and use ms access as frontend.
I have two tables (persons and managers), manager is derived from persons (a 1:1 relation), thus i created a view managersFull which is basically a:
SELECT *
FROM `managers` `m`
INNER JOIN `persons` `p`
ON `m`.`id` = `p`.`id`
id in persons is autoincrementing and the primary key, id in managers is the primary key and a foreign key, referencing persons.id
now i want to be able to insert a new dataset with a form in ms access, but i can’t get it to work. no error message, no status line, nothing. the new rows aren’t inserted, and i have to press escape to cancel my changes to get back to design view in ms access.
i’m talking about a managers form and i want to be able to enter manager AND person information at the same time in a single form
my question is now: is it possible what i want to do here? if not, is there a “simple” workaround using after insert triggers or some lines of vba code?
thanks in advance
The problem is that your view is across several tables. If you access multiple tables you could update or insert in only one of them.
Please also check the MSDN for more detailed information on restrictions and on proper strategies for view updates
Assuming ODBC, some things to consider:
make sure you have a timestamp field in the person table, and that it is returned in your managers view. You also probably need the real PK of the person table in the manager view (I'm assuming your view takes the FK used for the self-join and aliases it as the ID field -- I wouldn't do that myself, as it is confusing. Instead, I'd use the real foreign key name in the managers view, and let the PK stand on its own with its real name).
try the Jet/ACE-specific DISTINCTROW predicate in your recordsource. With Jet/ACE back ends, this often makes it possible to insert into both tables when it's otherwise impossible. I don't know for certain if Jet will be smart enough to tell SQL Server to do the right thing, though.
if neither of those things works, change your form to use a recordsource based on your person table, and use a combo box based on the managers view as the control with which you edit the record to relate the person to a manager.
Ilya Kochetov pointed out that you can only update one table, but the work-around would be to apply the updates to the fields on one table and then the other. This solution assumes that the only access you have to these two tables is through this view and that you are not allowed to create a stored procedure to take care of this.
To model and maintain two related tables in access you don’t use a query or view that is a join of both tables. What you do is use a main form, and drop in a sub-form that is based on the child table. If the link master and child setting in the sub-form is set correctly, then you not need to write any code and access will insert the person’s id in the link field.
So, don’t use a joined table here. Simply use a form + sub-form setup and you be able to edit and maintain the data and the data in the related child table.
This means you base the form on the table, and not a view. And you base the sub-form on the child table. So, don't use a view here.