Will Entity Framework and SQL Server lock a object/record while deleting it - asp.net-mvc-3

I am deleting some objects and rows using two methods inside my asp.net MVC web application: first approach includes deleting an Entity Framework object, such as:
public void DeleteMyObject(MyObject a)
{
entities1.MyObject.Remove(a);
}
while the second approach is calling a stored procedure from my repository method to delete a database row such as:
public void Deleteuserclass(string a, int u)
{
entities1.deleteuserclass(a, u);
}
which calls the following stored procedure:
ALTER PROCEDURE dbo.deleteuserclass
#userid nvarchar(50),
#classid int
AS
Begin
Delete from Users_Classes where UserID = #userid AND ClassID = #classid
if ##rowcount = 0
Raiserror('No record deleted',1,16)
END
Using any of the above two approaches; can I be confident that if two delete requests for deleting the same object arrive at the server at the same time, then only one request will delete the record from the database and the other request will receive an exception (I mean will the Entity Framework or the SQL Server database lock the row while it is being deleted ?)?
BR

One or the other will execute first.
If your stored procedure is execured second you will get an exception due to the if statement in the stored procedure.
If the EF command is executed second there will be a OptimisticConcurrencyException, see: EF eqivalent for rows affected of SqlCommand.ExecuteNonQuery

Related

Spring Boot how execute stored procedure multiple times?

I need to execute a procedure multiple times with the requestbody. For now, i am using for loop to do that, but it is not a good way. For example, when the one request is failed, catching that request is a problem. See for the example usage.
Implementation of stored procedure with for-loop;
**Controller**
public void runSP(
#RequestBody List<IdNoteModel> idNotes
){
getService().runSP(idNotes);
}
**Service**
public void runSP(List<IdNoteModel> idNotes){
for (IdNoteModel idNote : idNotes){
getRepository().runSP(idNote);
}
}
**Repository**
#Query(nativeQuery = true, value = "EXECUTE PROCEDURE SP_RUN_ID_NOTE(:id, :note)")
void runSP(Long id, String note);
Is there a better way to run stored procedures multiple times? or do you have an idea to catch the failed requests?
You can use one stored procedure in which you can use the cursor to execute the procedure (SP_RUN_ID_NOTE) multiple times. In that stored procedure, you can also use rollback for something to fail. In your above case, you can store request body input in the table and then call procedure while taking input row from that table.
You can use #Retryable for this purpose and also you can catch exceptions and log requests with #Recover

Mybatis Oracle Stored Procedure

I am having problem calling oracle Stored Procedure and getting Output parameters from Oracle Stored Procedure.
Here is my mapper
AppUserMapper.java
public interface AppUserMapper {
#Select(value= "{ CALL sp_check_user( #{userId, mode=IN, jdbcType=VARCHAR }, #{userPwd, mode=IN, jdbcType=VARCHAR}, #{userType, jdbcType=VARCHAR, mode=OUT} )}")
#Options(statementType = StatementType.CALLABLE)
Object getUserType(String userId,String UserPwd);
}
Dao call
Map<String, Object> retrurnStatus = (Map<String, Object>) appUserMapper.getUserType(userId,UserPwd);
Here is Stored Procedure code
CREATE OR REPLACE PROCEDURE HR.sp_check_user (userId VARCHAR,userPwd VARCHAR, userType OUT VARCHAR )
AS
BEGIN
BEGIN
select user_type into userType from appuser where USER_ID = userId and USER_PWD = userPwd ;
EXCEPTION
WHEN NO_DATA_FOUND THEN
userType := 'Invalid';
END ;
END ;
/
It is executing stored procedure but giving error
DEBUG 2014-04-12 09:51:56,948 org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl: ==> Preparing: { CALL sp_check_user( ?, ?, ? ) }
DEBUG 2014-04-12 09:51:57,103 org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl: ==> Parameters: abc(String), abc1(String)
Could not complete request
java.lang.NullPointerException
at com.appuser.dao.AppUserDaoImpl.getUserType(AppUserDaoImpl.java:33)
I had been trying multiple options but could not find sample which I can take as is and try.
I will relay appropriate help on this as I have been trying to use oracle stored procs in mybatis with multiple input and output parameters.
Can someone provide simple example for calling Oracle stored procedure using mybatis for multiple input output parameters?
Jeff Butler says in mybatis-user group:
For stored procedure parameters, MyBatis will map both input and
output parameters to properties in the parameterType.
You can try sending a Map, POJO or three annotated variables having userId, userPwd and userType. After the SP is called, MyBatis will set the OUT parameter to userType.
I cannot try it now, I'll try to edit the answer later. But can you try these,
1) Define your function as follows, and check if userType is updated after you call the SP.
void getUserType(Param("userId") String userId, Param("userPwd") String userPwd, Param("userType") String userType);
or
2) Create a Map, add 3 key-value pairs, i.e. ("userId", 1234), ("userPwd", 666), ("userType, null) tuples. After you call the SP, you can try getting the userType value.
void getUserType(Map<String, Object> myMap);
or
3) Create a class with 3 variables (userId, userPwd, userType), getters, setters. Set userId and userPwd values. Call the SP. Then, userObj.getUserType().
void getUserType(UserClass userObj);

how to delete multiple rows of data with linq to EF using DbContext

Within a project I have a database table with the following columns
I would like to be able to delete from this table all rows which have a matching SharingAgencyId and ReceivingAgencyId values that I can pass in.
What I have tried so far:
public static ICollection<SecurityDataShare> UpdateSharedEntites(long conAgency, long recAgency)
{
ICollection<SecurityDataShare> agShares = null;
try
{
using (var context = new ProjSecurityEntities(string.Empty))
{
agShares = (from a in context.SecurityDataShares
.Where(c => c.ReceivingAgencyId == recAgency && c.SharingAgencyId == conAgency)
select a);
}
}
catch (Exception ex)
{
//ToDo
throw;
}
}
My thought process was to retrieve the records where the id's matched the parameters passed in and then using a foreach loop iterate through (agShare) and remove each row followed by saving my changes. With the current implementation I don't seem to have access to any of the Delete methods.
Looking to the example above I'd appreciate any suggestions on how to remove the rows within the table that contained a value of 43 and 39 using dbContext.
Cheers
If I understand right, your DbContext's properties, like SecurityDataShares should be typed as IDbSet<SecurityDataShare>. If that's correct, you should be able to use this Remove method.
foreach(var agShare in agShares) {
context.SecurityDataShares.Remove(agShare);
}
context.SaveChanges();
Be aware that this creates a separate SQL statement for deleting these objects. If you expect the number of objects to be rather large, you may want to use a stored procedure instead.
Entity Framework doesn't make it easy to run a single command to delete multiple rows (that I know of). My preference is to run a SQL statement directly for multi-entity updates/deletes using native sql with the dbcontext of sorts.
you can also pass datatable to the stored procedure with database contain dynamic type table of your type and
use that table into stored procedure for deleting matching rows from Database table.

Issue in mvc posting a new table and recording that tables ID in another table in the same post command

Ok so I've tried a number of different ways which work some times and don't others so I'd rly like to find out the sure fire way to ensure this process works correctly.
I have 4 tables with 1 table storing the other 3 tables Id upon each page submit.
Table One is created at the same time as table Two with table two being the form table and one just being a way to connect all 4 together
One O = new One();
_db.Twos.AddObject(T);
O.TId = T.Id;
_db.Ones.AddObject(O);
_db.SaveChanges();
this works but the other 2 tables have issues with 3 working and 4 breaking even with the same code as 3.
1 solution that I'd hate to use would be to pass each table via session or a model object right till the end and then submit them all together but that would open it up to more problems I think.
Edit-
I'm not exactly sure what else I can add but the basic problem is I have 1 core table with 3 sub tables and new records gets created in each table at different times.
3 saves
1st = new core record + 1 new sub table record - works
2nd = update core record + 1 new sub table record - works
3rd = update core record + 1 new sub table record - breaks
2nd/3rd save example code with Th being the table object passed in which represents the 3rd table and O being the core table as shown in the code near the top
O.Three = Th;
_db.SaveChanges();
This correctly pulls the ID and saves it to the core table on the 2nd save but not on the 3rd save even tho it's the same code and the tables have the same connections.
Each pull - OId being the Core tables Id so each table knows where to save too.
public ActionResult Three(int OId, FormCollection fc)
Each Push
[HttpPost]
public ActionResult Three(Three Th, FormCollection fc)
As nothing else but the references changes I think thats about it else which is relevant since everything it basically date/time assignments to table values which then get checked if ModelState.IsValid before it trys to save changes.
I've also tried to use UpdateModel but that hasn't worked either so anybody know of any other solutions for this ?
The id from the database for T.id in the line O.TId = T.Id; will not be relevant at that point in your code. You must call saveChanges(); for the id to be fed into the object.
Try:
One O = new One();
_db.Twos.AddObject(T);
_db.SaveChanges();
O.TId = T.Id;
_db.Ones.AddObject(O);
_db.SaveChanges();

hsqldb not showing reflection of insert query while runing with JUnit test

i am using hsqldb as database. i create LmexPostParamDao which has a method insertLmexPostParam(NameValuePostParamVO nameValuePostParamVO) which will insert data in databse. for testing this method i used JUnit test to insert some data in hsqldb.
my JUnit test method is as below:
#Test
public void testInsertLmexPostParam(){
String lmexPostParamId = UUID.randomUUID().toString();
NameValuePostParamVO nameValuePostParamVO = new NameValuePostParamVO();
nameValuePostParamVO.setLmexPostParamId(lmexPostParamId);
nameValuePostParamVO.setParamName("adapter_id");
nameValuePostParamVO.setParamValue("7");
lmexPostParamDao.insertLmexPostParam(nameValuePostParamVO);
}
my insert method is as below:
#Override
public void insertLmexPostParam(NameValuePostParamVO nameValuePostParamVO) {
String insertQuery = "insert into LMEX_POST_PARAM(lmex_post_param_id, param_name, param_value) values (?,?,?)";
String[] paramArr = { nameValuePostParamVO.getLmexPostParamId(), nameValuePostParamVO.getParamName(), nameValuePostParamVO.getParamValue()};
int update = adapterJdbcTemplate.update(insertQuery, paramArr);
System.out.println(update);
}
when i run my test case it's returning me 1 as output which is result of adapterJdbcTemplate. which means data inserted sucessfully. but when i see my database it is not showing me a that row which inserted. and when i debug my testcase method with same values it's give a exception : Data integrity violation exception. and after this exception when i see my database it's showing that row in my database. what will be the problem. i do not. when i see code it's look like everything is fine. help me to resolve this.
Thank you
Check your CREATE TABLE statement for LMEX_POST_PARAM. The CHAR and VARCHAR types must be defined as CHAR(N) and VARCHAR(N), with N large enough to accept the values that you insert. For example, VARCHAR(100).
If your problem is the database is not showing the successful insert, then you should create your database with WRITE_DELAY = 0 or false. See the HSQLDB documentation for the version you are using.

Resources