Our customer has given the access to views in which there is no primary key is defined. I know Entity Framework needs a primary key for table to identify.
But for views not having primary key is it still possible to query.
I try to find but always Entity Framework gives error saying:
Error: : EntityType 'ViewWeight' has no key defined. Define the key for this EntityType.
I understand key is important for tables, but for views just to read is there any hack or way to read the values without modifying the view itself.
It's not possible in Entity Framework to have Entities without primary key.
Try to get a possible unique key from the views, combining columns, ... to create a unique primary key.
If is not possible there is a workaround, if is only a queryable view, with out need to do other operations with retrieved values such delete or update. Modify the view to add NEWID() , it will generate a unique GUID ID for each row, use this new column as primary key for your entity.
CREATE VIEW FooView AS
SELECT SELECT NEWID() AS ID,
COLUMN_A,
COLUMN_B
.....
The problem is if you repeat the same query every time you will get different ID for the same row.
Updated
If you can't not modify the view you can use Entity with a raw Sql, create the raw sql as
List<MyView> myViewItems = context.MyView.SqlQuery("SELECT NEWID() AS ID, MyView.* FROM MyView").ToList();
In your models add
public Guid ID { get; set; }
And configure the new property as the primary key.
But be careful, because there is not compilation check with this kind of code.
I create the view which includes a primary key. Ensure that all fields in the view are of a specific data type:
Number(9) rather than Number, use CAST to get the type you want
Then add a disabled primary key constraint. It won't do anything except be recognized by entity framework as a key
alter view emp_view add constraint vemp_pk primary key (empno) disable
Related
In my current project, I have to sync multiple client databases to one server database. I had given a try with Microsoft's sync framework and is not useful in my case. Therefor I have to do sync manually. for that I need to change primary key constraints from int to guid in all the tables.
Problem is this primary keys are also referred as foreign key in other tables.
I had referred below,
Moving from ints to GUIDs as primary keys
I am not good at SQL. I understood the logic but actual implementation is very tough for me.
ALTER TABLE MyTable
ADD GuidCol NVARCHAR(50) NOT NULL,
CONSTRAINT AK_GuidCol UNIQUE(GuidCol)
in above code I tried to add a column GuidCol as unique column after googling a lot. But
I don't know How can I fill values in the newly created column?
How can I make this column as PK after assigning value(s)?
How to make sure that this process won't break existing foreign key constraints?
I don't know How can I fill values in the newly created column?
The link you provided gives a solution:
Create a new column for the guid value in the master table. Use the
uniqueidentifier data type, make it not null with a newid()
default so all existing rows will be populated.
So your code should look like this:
alter table myTable add GuidCol uniqueidentifier not null default newid()
How can I make this column as PK after assigning value(s)? How to
make sure that this process won't break existing foreign key
constraints?
The same answer tells you:
Create new uniqueidentifier columns in the child tables.
Run update statements to build the guild relationships using the
exisitng int relationships to reference the entities.
Drop the original int columns.
Use the same uniqueidentifier type as in previuos statement, but instead of providing defalut, run the update statements joining the tables on existing integer id and set in the child's column the corresponding parent value.
Now you have child-parent relationship established but without constraints on them. Drop int columns and create PK and FK on new guid columns
I am facing issues to add a view from oracle to entity framework.
First, the error was that can not infer a primary key from the colums, so I add a pk to the view.
Now says that primary key is not valid because a part of it is nullable.
Oracle query:
CREATE VIEW ALERTEST."GET_SPMONITORES"
AS
select
CAST(NVL(procedure_name, '')AS VARCHAR(200)) AS SP
from all_procedures
where object_name = 'PAC_NL_MONITORES' AND procedure_name IS NOT NULL
;
ALTER VIEW GET_SPMONITORES
ADD CONSTRAINT GET_SPMONITORES_PK PRIMARY KEY (SP) DISABLE NOVALIDATE;
I recently came across the same issue, trying to load a VIEW into EF with Oracle doing its best to wreck all of my tests in making a column show as NOT NULL.
I finally was able to do so using this.
Create a new table
CREATE TABLE "KEY_TABLE"
( "MY_KEY" NUMBER NOT NULL ENABLE,
CONSTRAINT "KEY_TABLE_PK" PRIMARY KEY ("MY_KEY")
);
INSERT INTO KEY_TABLE (MY_KEY) VALUES (1);
Then, create a VIEW that will have both your original view and this new table
CREATE VIEW "GET_SPMONITORES_KEY"
AS
select
my_key, sp
from key_table, GET_SPMONITORES
where my_key = 1
This will then give you a view :
describe "GET_SPMONITORES_KEY";
Name Null Type
------ -------- -------------
MY_KEY NOT NULL NUMBER
SP VARCHAR2(200)
You can now import this GET_SPMONITORES_KEY into EF and thoroughly ignore the my_key column afterwards. You will be able to use this view in any LINQ to SQL statements without any issues.
I have a view that returns the id (PK) of 3 separate tables and I'm able to link them to their corresponding tables in my LINQ to SQL statements so I can return their corresponding EntityObjects.
Hope this helps
You can cheat here a little bit. You don't have to have a primary key defined in the database. You do, however, need to define the primary key inside Entity Framework for the POCO. Thus, you could just figure out what uniquely identifies a record and then mark the fields that are part of that primary key with either [Key] attribute on the POCO or via Fluent API. If you are auto generating this with T4 templates, you'd have to manually add that to the Fluent API only.
If you're primary key is incorrect, though, it will crash if two records end up with the same key.
A primary key cannot be a nullable field, however. If there is no possible way to uniquely identify this data, I would just return a new Guid() in the view and just rely on that being unique to get around this. Though, I'm not entirely sure how you are using this data, so not sure if that would be a problem in the future.
This question already has answers here:
Should a database table always have primary keys?
(11 answers)
Closed 9 years ago.
I have a table called 'Date Restriction' and it basically holds the following properties:
DayId : int
DateFrom : datetime
DateTo : datetime
EventId : int // this is a foreign key
Now the way I would access this is to get the event I want and then look at the associated Date Restrictions.
Is it good practise or recommended to add a primary key column to this table if I never have to reference the date restriction alone?
You should always have a primary key. Having a primary key will allow SQL Server to physically store the data in a more efficient manner. A primary key also allows Entity Framework to easily uniquely identify a row.
Look for a natural key across your columns. If a single EventId will only ever have one row in this table, create a primary key on EventId.
If there is not a natural key, add a surrogate key column to your table and make it an identity.
As a database design practice, it is always recommended to have primary keys. Even if your application does not directly reference the DateRestriction Table, having a unique identification for a row will give you benefits not only on the SQL side but it will also allow entity framework to easily map the table (without going through any extra hoops).
You need to tell EF how to uniquely identify a row in your Database. If each event only appears once in the table you can make the EventId both the primary key and a foreign key. You could also make all three columns a composite primary key. For example:
class DateRestriction {
[Key, Column(Order=0)]
public DateTime DateFrom {get;set;}
[Key, Column(Order=1)]
public DateTime DateTo {get;set;}
[Key, Column(Order=2)]
public int EventId {get;set;}
}
I recommend having a surrogate key and creating a unique index using the natural key.
If this table in your database directly referenced by another table, then no. Without the rest of your structure I'm not entirely sure. So I'll provide a general rule of thumb with an example:
Customer Table:
Id
Name
Last
But you wouldn't Query an individual Address, not without linking it to a person. So you have this second table called Address.
CustomerId
Street
City
Zip
State
So this one Customer will always have a tied address, so defining a Foreign Key is acceptable. Now, if a Customer was allowed have more then one Address then yes, you would need a Primary Key so the structure stands on its own.
If that particular data is always tied to another table, you can just define a Foreign Key. Obviously your implementation and access to your database may have an impact. So you'll have to be wary. If your utilizing different technologies such as:
Entity Framework
Ado
etc
So being aware of implementation and design of both your database and application.
However, without a Primary Key you'll have to define Indexes so that you can optimize your database. As the Primary Key is always Indexed.
The surrogate key with an index will suffice.
Sorry if I misunderstood your question, but hopefully this points you in the right location.
I'm working with a legacy SQL Server database which has a core table with a bad primary key.
The key is of type NVARCHAR(50) and contains an application-generated string based on various things in the table. For obvious reasons, I'd like to replace this key with an auto-incrementing (identity) INT column.
This is a huge database and we're upgrading it piece-by-piece. We want to minimize the changes to tables that other components write to. I figured I could change the table without breaking anything by just:
Adding the new Id column to the table and making it nullable
Filling it with unique integers and making it NOT NULL
Dropping the existing primary key while ensuring there's a uniqueness constraint still on that column
Setting the new Id column to be the new primary key and identity
Item 3 is proving very painful. Because this is a core table, there are a lot of other tables with foreign key constraints on it. To drop the existing primary key, it seems I have to delete all these foreign key constraints and create them again afterwards.
Is there an easier way to do this or will I just have to script everything?
Afraid that is the bad news. We just got through a big project of doing the same type of thing, although our head DBA had a few tricks up his sleeve. You might look at something like this to get your scripts generated for the flipping of the switch:
I once did the same thing and basically used the process you describe. Except of course you have to first visit each other table and add new foreign key pointing to the new column in your base table
So the approach I used was
Add a new column with an auto incrementing integer in the base table, ensure it has a unique index on it (to be replaced later by the primary key)
For each foreign key relationship pointing to the base table add a new column in the child table. (note this can result in adding more than one column in the child table if more than one relationship)
For each instance of a key in the child table enter a value into the new foreign key field(s)
Replace your foreign key relationships such that the new column now serves
Make the new column in the base table the primary
Drop the old primary key in the base table and each old foreign key in the
children.
It is doable and not as hard as it might sound at first. The crux is a series of update statements for the children table of the nature
Update child_table
set new_column = (select new_primary from base)
where old_primary = old_foreign
I have the following table:
CREATE TABLE [dbo].[Exception] (
[ExceptionID] INT IDENTITY (1, 1) NOT NULL,
[ParentExceptionID] INT NULL,
[ApplicationID] INT NOT NULL,
[TypeName] VARCHAR (256) NOT NULL,
[Message] VARCHAR (MAX) NULL,
[StackTrace] VARCHAR (MAX) NULL,
[MachineName] VARCHAR (128) NULL,
[UserName] VARCHAR (64) NULL,
[CreatedOn] DATETIME NOT NULL
)
This is used to store exceptions that happen in applications. I have a foreign key as such:
ALTER TABLE [dbo].[Exception] ADD CONSTRAINT [FK_ParentException_Exception]
FOREIGN KEY ([ParentExceptionID])
REFERENCES [dbo].[Exception] ([ExceptionID])
ON DELETE NO ACTION ON UPDATE NO ACTION;
Why I designed it as ParentExceptionID instead of InnerExceptionID, I couldn't tell you. This definitely makes it extra confusing modeling this in E.F. It's entirely arbitrary, though, as you can express the same data either way.
As you should know, an Exception can only have one inner exception. However, this schema allows multiple rows to claim to have the same ParentExceptionID. Logically, this never happens, but the data supports it.
Normally when I want to make a non-recursive one-to-one relationship in my schema I either use the same primary key column name in both tables, or I add a unique index to the foreign key of the second table.
The former would look like this:
Table A
PrimaryKey int
[...]
Table B
PrimaryKey int
[...]
Or the other way:
Table A
PrimaryKeyA int
[...]
Table B
PrimaryKeyB int
PrimaryKeyA int unique references A.PrimaryKeyA
[...]
In either case SQL diagrams and other tools will recognize this as a one-to-one relationship. Entity Framework only recognizes the first pattern, though, I've read.
My problem is, with a recursive foreign key, I can't use either pattern. I obviously can't have the first pattern because I have only one table. I can't use the second because I can't have a unique index on the foreign key column since there will be more than one row that has a NULL ParentExceptionID. Man, I wish SQL Server allowed a unique index that didn't force NULL to also be unique!
When I try to make an E.F. model from this schema it sees that multiple rows can claim to have the same ParentExceptionID, and it forces me to model this as a 0..1 -> *. I can't see any way to stop this. My Exception entity has an InnerException navigation property and it's a collection. Clearly, this is not what I need. If I try to change the multiplicity of the association and force it to be 0..1 I get a build error:
Multiplicity is not valid in Role 'InnerException' in relationship 'FK_ParentException_Exception'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be *.
Is there any way to do what I want? Even if that means changing my schema, I might consider it. Right now I'm thinking it's impossible.
No there is no way to map this in EF and even Unique index on the foreign key will not help you because current version of EF doesn't have support for unique keys.
The only way is to map it as one-to-many and hide the real navigation property as for example internal member. Instead of that you will expose another property (not in the entity diagram) in your partial part of the entity class which will allow definition of only single inner exception (it will simply work with the first item from the internal collection).
The problematic part of this solution would be eager loading of related exception because you can't eager load custom properties but only navigation properties.