Can't access Entity Framework table with no primary key - c#

I am creating an application to transfer data from one database into another for a new application and I am running into an issue access some of the data in the old database. The old database was created using Ruby on Rails and they way it was designed and created through Rails, the database in SQL Server has no primary keys and all the columns are nullable. The new database was designed and built in SQL Server with proper keys and nullable columns. Since both databases are in SQL Server I wanted to use Entity Framework Database First to make the data transition easier.
In the EF Desginer I was able to assign entity keys to all of the tables except for one (Response), which is keeping me from correctly accessing the data in the table. The table definition is as follows:
assess_id [int] NULL
person_id [int] NULL
question_id [int] NULL
question_version [int] NULL
answer_id [int] NULL
answer_version [int] NULL
text [nvarchar(4000)] NULL
created_at [datetime] NOT NULL
updated_at [datetime] NOT NULL
Because of the allowed records the primary key should consist of
assess_id
person_id
question_id
question_version
answer_id
answer_version
but there may be multiple answer_id and answer_version records to the same question_id and question_version or the answer_id and answer_version are null so I cannot use that. Any subset of this key would not allow me to properly retrieve all the data. Also I cannot use the created_at or updated_at columns as there are multiple instances of rows being written with the same time stamp.
I only need to read the data, not write, since it is being transformed into the new database and there is no way for me to change the existing database. Is there any way around the key issue?

Before I answer I would like to point out that this solution only works for read-only situations and if you need to write to the table it will not help. In that case I point you to this answer where you will find some help.
I managed to find a work around for this scenario and while easy enough to use, I would not consider it optimal.
In order to get around the key issue, I picked a primary key that would at least not fail a null check, in this case just the assess_id and person_id columns. This let me build without any errors but I still could not retrieve all the data correctly.
The workaround is to use a SqlQuery on the database.
var responses = context.Database.SqlQuery<Response>("SELECT * FROM dbo.responses");
This executed the query on the whole database and casted the result set into a list of responses with the correct data. Make sure you execute the query on the database and not the table, otherwise the incorrect key specified in the designer will be used and you won't get the correct data back.

Put your SQL in a stored procedure and call that from your application.
If you cannot modify the source database, you can put the stored procedure in the destination.

Related

How do I working with objects that can change from one client to another

I have a problem where I data for an object, for example billing file, where the data elements are different from client to client. More specifically the number of fields within the data and of different names. I am looking for a solution when working with the objects in C#.
Currently I have created tables for each client. The fields are specific to the client and I use a mapping process when uploading data. I also have dynamic queries in SQL Server to handle all crud processes. It all works pretty well but I believe there is a better solution and I believe saving Json data would be one of them. Pulling the Data I first query the headers of the table and then map the data to those headers for data grids and such. Again, I already have a working solution, but I believe there is a better solution and I am looking for suggestions with examples. By the way, I have thought about dynamic object, in C#, but it would appear you have to know what fields of the object are upfront.
I suggest that you should create mapping table, but there is no need to use something like dynamic sql, here are tables:
create table d_billing_object -- one row here means one field from your question
(
id int not null identity (1, 1) primary key
,name nvarchar(255) not null
)
create table d_billing_client
(
id int not null identity (1, 1) primary key
,name nvarchar(255) not null
)
create table d_billing_mapping
(
billing_client_id int not null
,client_billing_object_id int not null
,billing_object_id int not null
,constraint PK_d_billing_mapping primary key (billing_client_id, client_billing_object_id, billing_object_id)
,constraint FK_d_billing_mapping_d_billing_object foreign key (client_billing_object_id) references d_billing_object (id)
,constraint FK_d_billing_mapping_d_billing_object_2 foreign key (billing_object_id) references d_billing_object (id)
,constraint FK_d_billing_mapping_d_billing_client foreign key (billing_client_id) references d_billing_client (id)
)
After that you just need to create all billing objects and use them in mapping table for all clients you have.

Advance allotment of a primary key in a SQL Server table using C#

I have a database table Contact, in my application layer I'm getting a request from the client (i.e., Web API HTTP request) and I'm pushing the data into MSMQ.
I also have a Windows Service which receives the message from the respective MSMQ and processes the data. It inserts the data into the respective database table Contact.
SQL Server table structure of Contact:
CREATE TABLE [dbo].[Contact]
(
[ContactId] [int] IDENTITY(1,1) NOT NULL,
[FirstName] [varchar](50) NOT NULL,
[LastName] [varchar](50) NOT NULL,
[Email] [varchar](255) NOT NULL,
[Mobile] [varchar](10),
[CreatedDate] [datetime2](7) NOT NULL,
CONSTRAINT PK_Contact PRIMARY KEY (ContactId)
)
In this process, I need to send the primary key of the table Contact because the primary key is the Id of Contact. In the response, the client expects the Contact Id.
It is possible to allot an Id of Contact before data is inserted? or kindly assist me.
Please let me know changes required in the table structure.
Use GUID.
Generate GUID and pass it to INSERT.
Use this GUID for primary key, or use guid to get Id AFTER insert (Add additional column, then later you could get row by this column).
Since you have multiple sessions running you can't use built-in functions to get the next id available but you can work around that.
The work around is quite simple. here's are the step
1 - create another table with :
contactid, integer, identity same as yours
id, guid
isUsed, bit, default 0
2 - generate for each application that is running a guid when it starts
3 - when ready to create a contact in your window query the new table where the id is equal to your generated guid and where the isUsed is false, if there is any take that Contactid as it's not used yet, otherwise insert a new record in that table with your guid and isused as false and query again. this will generate a id just for your session.
4 - remove the identity on the contact table as id will come from the other table with identity and those are unique so no clashing possible
If you want to know which will be the next identity value, there is a built-in function for that. Nevertheless doing what you are suppposed to do is not recomended because other sessions may insert in that table. You may want to use other method of creating a numeric ID for your table, or just insert some data to "allot" and the updating with your real values. It seems a lot of work and I would recomend to insert the data and then getting the real ID with SCOPE_IDENTITY() function. That would be much secure.
Anyway, here is the function that will return that next autonumeric value:
SELECT IDENT_CURRENT('Contact') + 1

EF Code First From DB not creating Entities for all tables

I have an existing Database I am trying to use Entity Framework Code First From Database to generate C# entities for. To do this I am doing Add -> New Item -> ADO.NET Entity Data Model -> Code First from database inside Visual Studio 2015. When I go though the Entity Data Model Wizard I see that every table is selected but when the import finishes entities for some of the tables where not created. I have tried this twice and double checked that the table with no entities are indeed selected for import. No errors are thrown during the import so I am not sure why some of the tables are missing there entitles. What might be going wrong and how do I get an entities for every single selected table?
SQL Create Table Code for one of the missing tables:
CREATE TABLE [dbo].[ProgramControl] (
[CodeName] VARCHAR (80) NULL,
[CodeValue1] VARCHAR (50) NULL,
[CodeValue2] VARCHAR (50) NULL,
[CodeValue3] VARCHAR (50) NULL,
[CodeValue4] VARCHAR (50) NULL,
[Description] TEXT NULL
);
EF code-first requires the use of a primary key on every entity, so the tool is not able to map these tables.
It looks like you might be able to work around this with some trickery, but adding a PK to every table is almost certainly the best approach.
If Table does not have at least one parameter not null ADO.NET will not generate the class. I don't know if it is a bug, just happened to me.
It is not necessary to have a primary key but a not null.

Persisting Object Graph to SQL Server in a single transaction

I am having an issue coming up with a solution that I think must be a common problem to be solved by anyone writing to a database. I keep thinking that there is an obvious solution that I'm overlooking and that's why I can't find an appropriate existing question here.
Imagine a situation where you need to let a user create a "Class", with "Students", and each "Student" is assigned one or more books. You have a well defined hierarchy, Class->Student->Book.
You have the following tables:
CREATE TABLE Classes (
ClassId int identity(1,1) primary key,
ClassName nvarchar(255)
)
CREATE TABLE Students (
StudentId int identity(1,1) primary key,
ClassId int,
StudentName nvarchar(255),
StudentImage image
)
CREATE TABLE StudentBooks (
StudentBookId int identity(1,1) primary key,
StudentId int,
BookName nvarchar(255)
)
With this contrived scenario, what are my options for saving this entire graph of new objects, while letting SQL server assign the identity columns, and keeping it all in one transaction? Assuming that a class has maybe 30 students, and each student has several books assigned.
I could create a transaction and make a separate call for each row in each table, returning SCOPE_IDENTITY for each new parent object so I can save each child while keeping RI intact.
I could use XML. I would like to avoid that, as the graph includes a byte array.
Any other options? I thought about passing each level of the hierarchy in a table parameter. I'm not sure how or if that would work. (Wouldn't I have to define a table type for each of my tables, essentially duplicating the schema?)
I can use SQL server 2012 for this.
Thank you!
You can use Entity Framework to achieve what you want.
There are lots of tutorials out there, but a good starting point is this one:
MSDN on getting started with Entity Framework
or the linked page
MSDN overview page on getting started
I would recommend the EDMX approach for your use-case.

Approach for primary key generation

What is the best approach when generating a primary key for a table?
That is, when the data received by the database is not injective and can't be used as a primary key.
In the code, what is the best way to manage a primary key for the table rows?
Thanks.
First recommendation stay away from uniqueidentifier for any primary key. Although it has some interesting easy ways to generate it client side, it makes it almost impossible to have any idexes on the primary key that may be useful. If I could go back in time and ban uniqueidentifiers from 99% of the places that they have been used, this would have saved more than 3 man years of dba/development time in the last 2 years.
Here is what I would recommend, using the INT IDENTITY as a primary key.
create table YourTableName(
pkID int not null identity primary key,
... the rest of the columns declared next.
)
where pkID is the name of your primary key column.
This should do what you are looking for.
AUTO_INCREMENT in mysql, IDENTITY in SQL Server..
IDENTITY in SQL Server
and if you need to get know what you new ID was while INSERT-ing data, use OUTPUT clause of INSERT statement - so the copy of new rows is put to table-type param.
If for some reason generating unique ID at SQL is not suitable for you, generate GUID's at your app - GUID has a very hight level of uniquness (but it's not guaranteed in fact). And SQL Server has dedicated GUID type for column - it's called uniqueidentifier.
http://msdn.microsoft.com/en-us/library/ms187942.aspx

Categories