EF6.0 won't create associations VS2013 Legacy 2008R2 Database First - entity-framework

Working to create an EF6.0 connected DB with MVC5 in VSS2013. Previously the model worked, having been created with EF5.0, MVC3 and VSS2010.
Changes were made to the database on existing tables using MS SQL Express - adding some foreign integer keys on child tables pointing to a master parent record, and a single hand-entered test data record set was created for testing. Some extra properties were added. A couple of new unrelated tables.
The "Update Model From Database" picked up the table changes, but has refused to pick up these FK associations. ALL navigation was missing.
The model was deleted, recreated in EF6.0. Once again the EDMX file picks up all tables, and older FK associations. New ones are simply ignored.
There is no point adding tables here as examples, this is simple Parent Child FK stuff using ints. Scripted SQL shows FK constraints for old and new ones are comparable. I have dropped the model and recreated several times, with different ConnectionStrings, name changing in case of confusion. No joy.
I am totally confused as to why it can pick up some, but not others. I need some "gotcha" clues. Anyone?
EF6.0.0 MVC5.1 .NET4.5
Update: Non-Functional FK example
ALTER TABLE [dbo].[Cli_Address]
ADD CONSTRAINT [FK_Cli_Address_WebUserProfileX] FOREIGN KEY ([UserProfileFK]) REFERENCES [dbo].[WebUserProfile] ([UserID]);

You are hit by this:
http://social.msdn.microsoft.com/Forums/en-US/0ba27be1-d252-44c0-8e0b-7f129b578a2b/missing-navigation-properties-on-entity?forum=adodotnetentityframework
Caused by this unneeded index:
CREATE UNIQUE NONCLUSTERED INDEX [IX_WebProfile] ON [dbo].[WebUserProfile]
(
[UserID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Dropping the index, and everything Works
(I think you will have to drop and recreate the fks before you can drop the index)
UPDATE: I have fixed this, so this scenario is no longer broken , see https://entityframework.codeplex.com/workitem/667

Related

Why am I unable to create an index using low privileged user

I created a Role to which this user belongs to, and have set execute rights on multiple Schemas, however on Data Schema i need to be able to dynamically create and delete tables. Based on the screenshot, i gave all available permissions to the role (and user effectively) but when i try creating an index this is the error i get :
Could not create constraint or index. See previous errors
There are no previous errors :(
This is the code that should create the table and indexes :
CREATE TABLE [Data].[24C6B124-137C-4F06-B690-F80C0C0A1347]
(
[ApplicationId] [INT] NOT NULL,
[UUID] [UNIQUEIDENTIFIER] ROWGUIDCOL NOT NULL,
CONSTRAINT [PK_24C6B124-137C-4F06-B690-F80C0C0A1347]
PRIMARY KEY CLUSTERED ([ApplicationId] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];
ALTER TABLE [Data].[24C6B124-137C-4F06-B690-F80C0C0A1347]
ADD CONSTRAINT [DF_24C6B124-137C-4F06-B690-F80C0C0A1347_UUID]
DEFAULT (NEWID()) FOR [UUID];
ALTER TABLE [Data].[24C6B124-137C-4F06-B690-F80C0C0A1347] WITH CHECK
ADD CONSTRAINT [FK_24C6B124-137C-4F06-B690-F80C0C0A1347_Application]
FOREIGN KEY([ApplicationId]) REFERENCES [dbo].[Application] ([ApplicationId])
ON DELETE CASCADE;
rolling back...
If I execute same query with sa level user, it runs with no issues.
My best bet is that this is a permission problem related to some permission required to create indexes, but my search and experiments lead me nowhere.
As i posted a question, i figured it out so let me share :
I needed to add reference permission also on the table [dbo].[Application] that's in dbo Schema unlike table in question that's in Data Schema.

Trigger to update parent table based on max value of child table

this is my first foray into SSMS/T-SQL (coming from Access). I have a trigger setup that keeps the value of a column in a parent table always equal to the MAX value of a column a child table based on the key between them. To calculate the MAX I have a UDF defined that i Think works ok.
The problem I seem to have is that the trigger executes for EVERY key in the table and not just the one that got updated/deleted/inserted (or so is what I can glean from the debugger).
Here is the parent table:
CREATE TABLE [dbo].[factMeasures](
[MeasureID] [int] IDENTITY(1,1) NOT NULL,
[QARTOD] [int] NULL,
[Param] [char](10) NOT NULL,
[Value] [real] NOT NULL,
CONSTRAINT [PK_factMeasures] PRIMARY KEY CLUSTERED
(
[MeasureID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Here is the child table:
CREATE TABLE [dbo].[dt_QCflags](
[QC_ID] [int] IDENTITY(1,1) NOT NULL,
[fkMeasureID] [int] NOT NULL,
[RuleValue] [int] NOT NULL,
CONSTRAINT [PK_dt_QCflags] PRIMARY KEY CLUSTERED
(
[QC_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[dt_QCflags] WITH CHECK ADD CONSTRAINT [FK_dt_QCflags_factMeasures] FOREIGN KEY([fkMeasureID])
REFERENCES [dbo].[factMeasures] ([MeasureID])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[dt_QCflags] CHECK CONSTRAINT [FK_dt_QCflags_factMeasures]
GO
HEre is the UDF that calculates the MAX value of [RuleValue] for the input [MeasureID]
CREATE FUNCTION [dbo].[MaxQC](#MeasureID INT)
RETURNS INT
AS
BEGIN
RETURN
(SELECT
Max([dt_QCflags].[RuleValue]) AS Max_RuleValue
FROM
dbo.dt_QCflags
WHERE
dt_QCflags.fkMeasureID = #MeasureID
GROUP BY
fkMeasureID);
END
And here is the trigger on the child table:
ALTER TRIGGER [dbo].[UpdateQARTOD]
ON [dbo].[dt_QCflags]
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
UPDATE factMeasures
SET QARTOD = dbo.MaxQC(MeasureID) -- by QARTOD Definition, QARTOD flag is set to the MAX of all sub-test results
END
So what I want is for the column in the parent (factMeasures.QARTOD) to always contain the Maximum of the column in the child table (dt_QCFlags.RuleValue), for the given MeasureID value
When I debug this, it seems to be running the trigger for EVERY record in the parent table, so I think I need to modify the trigger, but i"m not sure how to get the MeasureID of JUST the record that was added/deleted/modified.
I'm guessing it has something to do with the "magic tables" inserted, deleted, etc. but I can't seem to get the syntax right.
Thanks!
I would argue that unless you have a very good reason, storing values that can easily be computed on a query level is a mistake.
This seems like one of many cases I've seen where people think they gain something by storing values on one table that's calculated from values of another table, but in fact the opposite is true - now you have two points of data that needs to be synchronized at all times, and since the process synchronizing them is a trigger, you don't really have control over that - it's quite easy to disable / enable triggers, for instance.
Therefore, My advice to you would be to remove that trigger all together and simply calculate the value when you need to.
Please note that since SQL Server supports max() over(partition by) meaning you don't even need a group by if you want to calculate the max of a column.
Updated Following your comments to the answer, it seems like you have a good reason to store these values.
Having said all that, here's a direct answer to the question you've asked.
In SQL Server triggers, the database enables you to query two special tables called inserted and deleted. These tables contains the data that was (or going to be, in case of instead of triggers) inserted or deleted to the table on which the trigger is declared.
Please note that in SQL Server, triggers are fired per statement, not per row. This means that the inserted and deleted tables might contain 0, 1 or many rows.
If you still want to calculate the value using triggers, I would advise a trigger for insert/update and another trigger for deletes.
This would make for much simpler code.
In the delete trigger, you left join to the deleted table:
UPDATE T
SET QARTOD = MaxValue
FROM factMeasures As T
JOIN
(
SELECT d.fkMeasureID, Max(t.RuleValue) As MaxValue
FROM Deleted AS d
LEFT JOIN dt_QCflags As t
ON d.QC_ID = t.QC_ID
GROUP BY d.fkMeasureID
) as D
ON T.MeasureID = D.fkMeasureID
In the insert/update trigger, you write a very similar code - but you don't need to refer to the physical table in this case, only the inserted table:
UPDATE T
SET QARTOD = MaxValue
FROM factMeasures As T
JOIN
(
SELECT fkMeasureID, Max(RuleValue) As MaxValue
FROM Inserted
GROUP BY fkMeasureID
) as I
ON t.MeasureID = I.fkMeasureID

EF DBFirst, table gets removed from model

Something strange is happening in my EF Database-first EDMX model.
I wanted to update the model after making some changes in the DB.
The update operation removed a table that did not received any changes. That table was present in the model for a long time and never had any problems.
Obviously, I'm getting the Error 11007 : Entity type 'MyTable' is not mapped.
I tried several things:
Close the EDMX without saving, retry: same problem.
Redo "Update Model from DB", check the box in front of the removed table... But it is not getting added to the model (?)
Close Visual Studio, retry: same problem.
Try in another EDMX (I have 5-6 models in the solution, all linked to the same (big) DB) : There the table is not removed (!)
Rename the table in the DB : With the new name, it IS added.
Clean the EDMX's XML from everything that is linked to that table, retry the update: no effect.
What could be causing a particular table to not be added in a particular emdx model file ? This seems like a bug to me.
NB. Before the table is removed, it is listed in the "Refresh" tab of the "Update from DB" Wizard.
VS 2017 15.4.2 (last update done the day before the problem appeared...?)
EDIT - More information :
The Table is named "DocumentStatuses" and formed of two columns.
CREATE TABLE [cov].[DocumentStatuses](
[Id] [int] NOT NULL,
[Label] [varchar](50) NOT NULL,
CONSTRAINT [PK_DocumentStatus] PRIMARY KEY CLUSTERED ( [Id] ASC )
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
The DocumentStatus entity maps the Id column to an enum. It worked fine until this problem appeared (but it continues to work fine for 2 other entity data models).
EDIT 2
I'm going crazy with this bug. It suddenly appeared, in the same edmx, for 5 others tables that are not linked to each other.
I tried to create another EDMX, with another name, and it has the same bug.
I tried to add tables one-by-one, and suddenly, the problems appears. No matter wich table I add, the 5 others that were present in the model simply disappear and I get the Error 11007.
If anyone has the tiniest idea, it is really welcome.
EDIT 3
I created a new solution, added my tables to a new entity data model... and the problems remains. EF REFUSES to map the tables.
Are there some logs that VS creates when we do "Update from database" ?.
Next step i'll try is to create a VM and try in it.
I "solved" the problem by renaming the table in the database.
This is only a workaround but it's all I could come up with.
I had created "separator" tables with names formed with 20 underscores. Like this : schema._________________________
So I had "separators" between my schemas in SSMS. These dummy tables were not mapped of course.
I removed them and... the problem disappeared !
This is a bug and I reported it:
https://github.com/aspnet/EntityFramework6/issues/418

How to enable cascading delete in Edmx Designer on many to many relation

I am using VS2012 and the Entity designer to generate both the database and the models. I have a very basic scenario of Table1 to Table1and2JoinTable to Table2. Something like Students, Classes, StudentClasses. You can have many students in many classes. I would like to have a cascading delete. So if you delete a student any rows in the StudentClass join table are deleted for that student id. Same for deleting a class any rows in the StudentClass are deleted for that class id. After setting up the many to many association in the designer and setting the cascade delete options you get the following error when you attempt to generate the database:
Error 132: End 'Student' on relationship 'Model1.StudentClass' cannot have operation specified since its multiplicity is ''. Operations cannot be specified on ends with multiplicity ''.
Here is a small example:
Here is the association created:
And the resulting error messages:
Here is a portion of the SQL code for generating the database tables:
-- Creating foreign key on [Students_Id] in table 'StudentClass'
ALTER TABLE [dbo].[StudentClass]
ADD CONSTRAINT [FK_StudentClass_Student]
FOREIGN KEY ([Students_Id])
REFERENCES [dbo].[Students]
([Id])
ON DELETE NO ACTION ON UPDATE NO ACTION;
-- This should be ON DELETE CASCADE ON UPDATE NO ACTION;
GO
-- Creating foreign key on [Classes_Id] in table 'StudentClass'
ALTER TABLE [dbo].[StudentClass]
ADD CONSTRAINT [FK_StudentClass_Class]
FOREIGN KEY ([Classes_Id])
REFERENCES [dbo].[Classes]
([Id])
ON DELETE NO ACTION ON UPDATE NO ACTION;
-- This should be ON DELETE CASCADE ON UPDATE NO ACTION;
GO
I know how to work around this by just editing the database script and add in the on delete cascade option. But, I don't want to do this because I am going to come back to the designer many times as the project grows and I don't want to have to remember this step every time.
Has anyone figured out how to resolve this?
It seems to be an edmx restriction, which I don't really understand. Code-first is perfectly capable of generating a junction table with two cascading ON DELETE constraints, but model-first and database-first do not allow the same configuration in the edmx. Normally, cascade actions are configured on the 'one' end of an association. Maybe it is too complex to check the validity of cascade actions on '*' ends (only when both ends are '*').
For the cascaded delete to happen with a context based on an edmx model, you have to load a parent and its children and then delete the parent.
var cls = db.Classes.Include(c => c.Students).Single(c => c.Id = 1);
db.Classes.Remove(cls);
db.SaveChanges();
The executed SQL statements show that the Class is fetched from the database in a JOIN statement with Student. Then the StudentClasss and the Class are deleted respectively.
Obviously, this is much more expensive than enabling cascaded delete in the database.
The work-around to modify the DDL each time after is was generated is not attractive, of course. But I think the only alternative is to make StudentClass part of the model and configure cascaded delete on the 'one' ends of the new associations. Or go code-first.
First of all make sure that you have an ON DELETE CASCADE specified in your Foreign Keys on database side.
I had similar problem and just adding ON DELETE CASCADE solve it instead of setting End1OnDelete and End2OnDelete properties.

Can't drop Index Constraint

I'm trying to first drop the index and then the PK (because ultimately I'm gonna need to do a truncate on this table).
Here's a screen shot of this table and constraints:
Here are the 2 constraints (code obtained from clipboard after I right-click them and do a create to clipboard in SQL 2008):
(the Primary Key)
ALTER TABLE [dbo].[Entry] ADD CONSTRAINT [PK_Entry_Id] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
(supposedly this is the create index code, after I do a right-click create to clipboard..but it's the same exact code! not sure why):
ALTER TABLE [dbo].[Entry] ADD CONSTRAINT [PK_Entry_Id] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Dropping the primary key should drop the index as well as the index was automatically created when you created the primary key.
You only need to drop the Foreign Key constraints when you need to truncate a table. This is to make sure there are no tables dependent on it.
You don't need to, and can't, drop the index associated with the primary key. All you need to do is drop the primary key and the index will be removed.
If you're going to truncate the data, you shouldn't have to drop the primary key though.
If you can't truncate the table, then you should remove foreign keys that reference this table. I assume that you removed foreign keys where this table references other tables, because we don't see any in your data.
Constant and index are not the same.
But in some syntax an index is referred to as a constraint.
You have 5 constraints and one index.
You did not like notice it has the same name in both spots PK_Entry_ID.
A PK is an index.
And an index does not prevent a truncate.
A FK prevents a truncate.
If you are tying to drop the index the why are you creating a script to create.
Create a script to drop and drop it.