简体   繁体   中英

Related tables inserting data

I have a little question.

Short description of the project: I'm working on a little API project written in C#. Inside this project I'm using the onion architecture, in short it's something like Controller -> Service -> Repository.

I have an Account controller, which manages create & update User and beside this I have a databas ewith the following tables:

User, Password, UserInformation

In User I have the following columns: Id(PK), userName and role.

In Password I have: User_Id(PK and FK to User - Id column), password and oldPassword (if necessary).

In UserInformation I have: User_Id(PK and FK to User - Id column), firstName, lastName and email.

As for inserting data, I have a separate class with string constants inside which are queries and I'm executing them by doing

sqlConnection.QueryAsync(QueryFromStringConstants, etcParams).

As I'm a little bit noobish with the SQL syntax and everything related to SQL in general(haha), my question is: if I create a User , how can I insert data into all 3 tables at the same time?

Thanks:)

Each insert requires a separate insert statement, and you should also get an identity value after each insert in order to use it for next insert, for example:

  1. insert user: INSERT INTO User (userName, role) VALUES (...)
  2. get user Id (I'm sure you definded it as IDENTITY): DECLARE @userId AS integer = (SELECT @@IDENTITY);
  3. insert user password (with user id obtained on prevoius step)
  4. insert user info (the same)

But you can also use Entity framework. You should create class User , which have virtual properties of type Password and UserInformation (also classes you should create as well). Then create a context which has a property DbSet<User> Users . In this case you just create a User instance, populate its fields, Password and UserInformation with correspondent instances of Password and UserInformation classes. Then use:

context.Users.Add(userInstanceVar);
context.SaveChanges();

That's all, EF will save all instances into your database. and also populates all identity values automatically.

If your Primary Key on your User table is an int or bigint , you use the function SCOPE_IDENTITY to get the PK.

set nocount, xact_abort on;   --recommended

begin transaction;

insert into user(User_Id,userName,...)
values(...);

declare @user_id int = scope_identity();   -- make sure this is the very next line after insert

insert into Password(User_Id,....)
values(@user_id,...);

insert into UserInformation(User_Id,....)
values(@user_id,...);

commit transaction;

If you are doing a multi-row insert, you can use Table-Valued Parameters. And then you will need the OUTPUT clause to output the IDs into a new table variable:

set nocount, xact_abort on;   --recommended

begin transaction;

declare @new_users table (user_id int, username varchar(50));

insert into user(User_Id,userName,...)
output inserted.user_id, inserted.username
select ...
from @users;

insert into Password(User_Id,....)
select u.user_id, ...
from passwords p
join @new_users u on u.username = p.username;

commit transaction;

I must say though, that I don't see the point in having a separate table for UserInformation , after all, you cannot have a User without UserInformation , so you shouold combine these into one.

You have to insert in the primary table then into the others. and use transaction to run the three statements. the following is an example using oracle procedure:

create or replace PROCEDURE InsertUser(.. params ...) 
as 
temp_id number;
BEGIN
insert into user(User_Id,userName,...) values(...) returning User_Id into temp_id;
insert into Password(User_Id,....) values(temp_id,...);
insert into UserInformation(User_Id,....) values(temp_id,...);
commit;
exception when others then rollback;
END InsertUser;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM