Facing issues while converting stored procedure into entity framework function - c#

I am new to entity framework. I have a procedure which save shipment data and I have to convert that procedure into entity framework function. For simple insert/update I am able to use entity framework but for this particular procedure I am facing issue.
In below procedure I have to update shipment table which have addressId, shipmenStatusId and serviceId as a foreign key. For particular shipment record if address is already exists then add existing address id in foreign key column otherwise first add new address into address table and then pick newly address id and update it into shipment address id column and same step for shipmentStatusType and service type.
Here is my procedure script.
CREATE PROCEDURE spSavePackage
#TrackingNbr VARCHAR(50),
#Carrier VARCHAR(10),
#PackageType VARCHAR(20) = NULL,
#ShippedDate DATETIME = NULL,
#ScheduledDate DATETIME = NULL,
#AddressLine1 VARCHAR(50)= NULL,
#AddressLine2 VARCHAR(50)= NULL,
#City VARCHAR(50) = NULL,
#State VARCHAR(2) = NULL,
#Country VARCHAR(2) = NULL,
#StatusDescription VARCHAR(50) = NULL
AS
BEGIN
DECLARE #AddressId int, #DeliveryStatusId int , #PackageId int
IF EXISTS (SELECT Id FROM tblPackages WHERE TrackingNr = #TrackingNbr AND Carrier = #Carrier)
BEGIN
IF EXISTS(SELECT Id FROM tblDeliveryAddress WHERE Address1 = #AddressLine1 AND Address2 = #AddressLine2
AND City = #City AND State = #State AND Country = #Country)
BEGIN
SELECT #AddressId = Id FROM tblDeliveryAddress WHERE Address1 = #AddressLine1 AND Address2 = #AddressLine2
AND City = #City AND State = #State AND Country = #Country
END
ELSE
BEGIN
SELECT #AddressId = MAX(Id) from tblDeliveryAddress
SET #AddressId = #AddressId + 1
INSERT INTO tblDeliveryAddress VALUES(#AddressId , #AddressLine1 , #AddressLine2 , #City , #State , #Country)
END
IF EXISTS (SELECT Id FROM tblDeliveryStatus WHERE Status = #StatusDescription)
BEGIN
SELECT #DeliveryStatusId = Id FROM tblDeliveryStatus WHERE Status = #StatusDescription
END
ELSE
BEGIN
SELECT #DeliveryStatusId = MAX(Id) FROM tblDeliveryStatus
SET #DeliveryStatusId = #DeliveryStatusId + 1
INSERT INTO tblDeliveryStatus VALUES(#DeliveryStatusId , #StatusDescription)
END
UPDATE tblPackages
SET DeliveryAddressID = #AddressId, DeliveryStatusId = #DeliveryStatusId,
ShippedDate = #ShippedDate , PackageType = #PackageType, ScheduledDate = #ScheduledDate
WHERE TrackingNr = #TrackingNbr AND Carrier = #Carrier
END
ELSE
BEGIN
SELECT #PackageId = MAX(Id) FROM tblPackages
SET #PackageId = #PackageId + 1
INSERT INTO tblPackages(Id , TrackingNr , Carrier) VALUES (#PackageId , #TrackingNbr , #Carrier)
END
END
For implementing functionality of this procedure I had created written following EF code.
public void UpdateShipments(List<Tuple<tblShipment, List<tblActivity>>> shipments)
{
tblShipment shipment = null;
var manager = ((IObjectContextAdapter)this._context).ObjectContext.ObjectStateManager;
foreach (var tuple in shipments)
{
shipment = tuple.Item1;
if (shipment.ConsigneeAddress != null)
{
shipment.ConsigneeAddressId = this.AddAddress(shipment.ConsigneeAddress).ID;
shipment.ConsigneeAddress = null;
}
else
{
shipment.ConsigneeAddressId = null;
shipment.ConsigneeAddress = null;
}
if (shipment.ShipperAddress != null)
{
shipment.ShipperAddressId = this.AddAddress(shipment.ShipperAddress).ID;
shipment.ShipperAddress = null;
}
else
{
shipment.ShipperAddressId = null;
shipment.ShipperAddress = null;
}
if (shipment.Service != null)
{
shipment.ServiceId = this.AddService(shipment.Service).ID;
shipment.Service = null;
}
else
{
shipment.ServiceId = null;
shipment.Service = null;
}
if (shipment.ShipmentStatusType != null)
{
shipment.ShipmentStatusId = this.AddStatusType(shipment.ShipmentStatusType).ID;
shipment.ShipmentStatusType = null;
}
else
{
shipment.ShipmentStatusId = null;
shipment.ShipmentStatusType = null;
}
this._context.Entry(shipment).State = System.Data.Entity.EntityState.Modified;
}
this._context.SaveChanges();
}
public tblAddressType AddAddressType(tblAddressType addressType)
{
tblAddressType tempAddressType = (from m in this._context.AddressTypes
where m.Type.ToUpper() == addressType.Type.ToUpper()
select m).FirstOrDefault();
if (tempAddressType == null)
{
tempAddressType = this._context.AddressTypes.Add(addressType);
this._context.SaveChanges();
}
return tempAddressType;
}
public tblAddress AddAddress(tblAddress address)
{
tblAddress tempAddress = (from m in this._context.Addresses
where m.AddressLine1.ToUpper() == address.AddressLine1.ToUpper() && m.AddressLine2.ToUpper() == address.AddressLine2.ToUpper() && m.City.ToUpper() == address.City.ToUpper()
&& m.StateProvinceCode.ToUpper() == address.StateProvinceCode.ToUpper() && m.CountryCode.ToUpper() == address.CountryCode.ToUpper()
select m).FirstOrDefault();
if (tempAddress == null)
{
address.AddressType = this.AddAddressType(address.AddressType);
address.AddressTypeId = address.AddressType.ID;
address.AddressType = null;
tempAddress = this._context.Addresses.Add(address);
this._context.SaveChanges();
}
return tempAddress;
}
After spending lots of time I found this way to implement it but I am not satisfied with this implementation. As I have to do lot's of hit for saving/updating shipment records which slowing the process. I need some optimized way to update shipment records so that for saving records I have to do only single database hit. I have multiple shipments record(records which is in collection) and I want single database hit to save records or 1 database hit to save one shipment records.
I tried to clarify my problems if any one facing issue to understand it then let me know. I am using c# as a programming language, sql server as a database and entity framework 6.0 as ORM.
Any help would be appreciated.
Thanks,
Awadhendra

I've had a similar problem in the past.
While it probably would be considered a hack by some others due to the nature of hard coding things that may change, if you also implement even simple integration tests (see later for an example) it is possible to keep track of such changes
Here is my solution
namespace ContextNamespace
{
public partial class ContextClass
{
public Task UpdateShipments(List<Tuple<tblShipment,
List<tblActivity>>> shipments)
{
return this.Database.ExecuteSqlCommandAsync("EXEC spSavePackage #p1 = #p1..",
new SqlParameter("#p1", shipments.???),....);
}
}
}
Along side this I have integration tests like this one, that their purpose is only to pass without exceptions -of course they can easily be fleshed out to include more proper checks
[TestMethod]
public async Task Sproc_Test()
{
//Create object
Context context = new Context();
await context.UpdateShipments(/*object*/);
}
An example of use in code is like this
public Task DoSomething(Object data)
{
return Context.UpdateShipments(data);
}

Related

I'm trying to insert values into SQL Server using two stored procedures with C# using Dapper

I'm running into an issue executing my connecting and inserting values into SQL Server where it's returning two different errors when using two separate models that have object references from separate classes.
The first stored procedure inserts into two separate tables. The main one has a foreign key, and the second table also has a foreign key, which has a relationship to the table coming from the second stored procedures primary key. Ultimately I am trying to find a way to execute the SQL script to pass in the values at the same time into both of these separate models.
I'm aware that I must insert first into the dbo.spUpload_Insert and then into dbo.spUploadVideo so the 'id' exists before hand. I also have verified if NULL is unchecked in my database it will insert into the appropriate tables without issue.
The first error:
Cannot insert the value NULL into column 'Video ID', table 'userMediaMetaData.dbo.Video Info Data'; column does not allow nulls. INSERT fails
The second error:
Cannot insert the value NULL into column 'ID', table 'userMediaMetaData.dbo.Basic Video Meta'; column does not allow nulls. INSERT fails
Here's the code causing the error in C# using Dapper for connecting to my database.
I'm using two different models:
public UploadInfo Upload(UploadInfo model)
{
List<String> Title = model.TitleOfVideo;
List <String> Description = model.DescriptionOfVideo;
List <String> Tags = model.Tags;
List <String> ContentId = model.Category;
int count = ContentId.Count;
string title = "";
string description = "";
string tags = "";
string contentID = "";
for (var i = 0; i < count; i++)
{
title = model.TitleOfVideo[i];
description = model.DescriptionOfVideo[i];
tags = model.Tags[i];
contentID = model.Category[i];
}
using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(GlobalConfig.CnnString("userMediaMetaData")))
{
var parameters = new List<DynamicParameters>();
var p = new DynamicParameters();
p.Add("#Title", title, dbType: DbType.String, direction: ParameterDirection.Input);
p.Add("#description", description, dbType: DbType.String, direction: ParameterDirection.Input);
p.Add("#tags", tags, dbType: DbType.String, direction: ParameterDirection.Input);
p.Add("#ContentID", contentID, dbType: DbType.String, direction: ParameterDirection.Input);
p.Add("#id", 0, dbType: DbType.Int32, direction: ParameterDirection.Output);
parameters.Add(p);
connection.Execute("spUploadVideo_Insert", parameters, commandType: CommandType.StoredProcedure);
model.Id = p.Get<int>("#id");
}
return model;
throw new NotImplementedException();
}
Second model:
public ExtractionFullModel Extraction(ExtractionFullModel model)
{
string group = model.Group;
string name = model.Name;
string value = model.Value;
if (count < tot_count)
{
if (name.Contains("Directory"))
{
_directory = name;
_directory_value = value;
}
if (name.Contains("Compatible Brands"))
{
_compatbrand = name;
_compatvalue = value;
}
if (name.Contains("Time Scale"))
{
_timescale = name;
_timescale_value = value;
}
if (name.Contains("Track Duration"))
{
_duration = name;
_duration_value = value;
}
if (name.Contains("Preferred Volume"))
{
_trackvolume = name;
_trackvolume_value = value;
}
if (name.Contains("Track ID"))
{
_trackid = name;
_trackid_value = value;
}
if (name.Contains("Image Width"))
{
_imgwidth = name;
_imgwidth_value = value;
}
if (name.Contains("Image Height"))
{
_imgheight = name;
_imgheight_value = value;
}
if (name.Contains("X Resolution"))
{
_xresolution = name;
_xresolution_value = value;
}
if (name.Contains("Y Resolution"))
{
_yresolution = name;
_yresolution_value = value;
}
if (name.Contains("Video Frame Rate"))
{
_video_frame_rate = name;
_video_frame_rate_value = value;
}
if (name.Contains("Media Create Date"))
{
media_create_date = name;
media_create_date_value = value;
}
if (name.Contains("Modify Date"))
{
_modify_date = name;
_modify_date_value = value;
//modifyDate_value = DateTime.Parse(_modify_date_value);
}
if (name.Contains("Audio Format"))
{
_audioformat = name;
_audioformat_value = value;
}
if (name.Contains("Audio Channels"))
{
_audiochannels = name;
_audiochannels_value = value;
}
if (name.Contains("Audio Bits Per Sample"))
{
_audiobits = name;
_audiobits_value = value;
}
if (name.Contains("Audio Sample Rate"))
{
_audio_sample_rate = name;
_audio_sample_rate_value = value;
}
if (name.Contains("Media Data Size"))
{
_media_data_size = name;
_media_data_size_value = value;
}
if (name.Contains("Image Size"))
{
_image_size = name;
_image_size_value = value;
}
if (name.Contains("Avg Bitrate"))
{
_avg_bitrate = name;
_avg_bitrate_value = value;
}
if (name.Contains("File Size"))
{
_file_size = name;
_file_size_value = value;
}
if (name.Contains("File Modification Date/Time"))
{
_file_mod_date = name;
_file_mod_date_value = value;
//FileModifyDate_value = DateTime.Parse(_file_mod_date_value);
}
if (name.Contains("File Access Date/Time"))
{
_file_access_date = name;
_file_access_date_value = value;
//FileAccessDate_value = DateTime.Parse(_file_access_date_value);
}
if (name.Contains("File Creation Date/Time"))
{
_file_create_date = name;
_file_create_date_value = value;
//FileCreateDate_value = DateTime.Parse(_file_create_date_value);
}
if (name.Contains("File Permissions"))
{
_filepermission = name;
_filepermission_value = value;
}
if (name.Contains("File Type"))
{
_filetype = name;
_filetype_value = value;
}
if (name.Contains("MIME Type"))
{
_MIMEtype = name;
_MIMEtype_value = value;
}
if (name.Contains("Compressor ID"))
{
_compressor = name;
_compressor_value = value;
}
++count;
}
if (count >= tot_count)
{
using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(GlobalConfig.CnnString("userMediaMetaData")))
{
var p = new DynamicParameters();
p.Add("#id", 0, dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("#FileDirectory", _directory_value);
p.Add("#CompatBrand", _compatvalue);
p.Add("#TimeScale", _timescale_value);
p.Add("#Duration", _duration_value);
p.Add("#TrackVolume", _trackvolume_value);
p.Add("#TrackID", _trackid_value);
p.Add("#ImgWidth", _imgwidth_value);
p.Add("#imgHeight", _imgheight_value);
p.Add("#XResolution", _xresolution_value);
p.Add("#YResolution", _yresolution_value);
p.Add("#VideoFrameRate", _video_frame_rate_value);
p.Add("#MediaCreateDate",media_create_date_value);
p.Add("#ModifyDate", _modify_date_value);
p.Add("#AudioFormat", _audioformat_value);
p.Add("#AudioChannels", _audiochannels_value);
p.Add("#AudioBits", _audiobits_value);
p.Add("#AudioSampleRate",_audio_sample_rate_value);
p.Add("#MediaDataSize",_media_data_size_value);
p.Add("#ImageSize",_image_size_value);
p.Add("#AvgBitRate",_avg_bitrate_value);
p.Add("#FileSize",file_to_int);
p.Add("#FileModDate", _file_mod_date_value);
p.Add("#FileAccessDate", _file_access_date_value);
p.Add("#FileCreateDate", _file_create_date_value);
p.Add("#FilePermission",_filepermission_value);
p.Add("#FileType",_filetype_value);
p.Add("#MIMETYPE",_MIMEtype_value);
p.Add("#CompressorID",_compressor_value);
connection.Execute("dbo.spUpload_Insert", p, commandType: CommandType.StoredProcedure);
model.Id = p.Get<int>("#id");
}
}
return model;
}
Here's the two separate stored procedures in SQL Server.
The first stored procedure with primary key id:
ALTER PROCEDURE [dbo].[spUploadVideo_Insert]
#Title nvarchar(50),
#Description nvarchar(MAX),
#Tags nvarchar(MAX),
#ContentID int,
#id int = 0 output
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.Upload (Title, Description, Tags, [Content ID])
VALUES (#Title, #Description, #Tags, #ContentID);
SELECT #id = SCOPE_IDENTITY();
END
This is the second stored procedure inserting into two tables with the foreign keys:
ALTER PROCEDURE [dbo].[spUpload_Insert]
#FileDirectory nvarchar(50),
#CompatBrand nchar(30),
#TimeScale text,
#Duration nvarchar(15),
#TrackVolume nvarchar(15),
#TrackID nvarchar(50),
#ImgWidth text,
#imgHeight text,
#XResolution nvarchar(50),
#YResolution nvarchar(50),
#VideoFrameRate nvarchar(15),
#MediaCreateDate nvarchar(25),
#ModifyDate nvarchar(25),
#AudioFormat text,
#AudioChannels text,
#AudioBits nchar(10),
#AudioSampleRate nchar(10),
#ImageSize nchar(10),
#MediaDataSize nvarchar(10),
#AvgBitRate nvarchar(50),
#FileSize nvarchar(10),
#FileModDate nvarchar(25),
#FileAccessDate nvarchar(25),
#FileCreateDate nvarchar(25),
#FilePermission nvarchar(50),
#FileType nvarchar(15),
#MIMEType nvarchar(20),
#CompressorID nvarchar(20),
#id int = 0 output
AS
BEGIN
SET NOCOUNT ON;
-- Adding video extraction information
INSERT INTO dbo.[Video Info Data]([File Directory], [Compatible Brands], [Time Scale], [Duration], [Track Volume], [Track ID], [Img Width], [Img Height],
[X Resolution], [Y Resolution], [Video Frame Rate], [Media Create Date], [Modify Date], [Audio Format], [Audio Channels],
[Audio Bits], [Audio Sample Rate], [Media Data Size], [Image Size], [Average Bit Rate], [MIME Type], [Compressor ID])
VALUES (#FileDirectory, #CompatBrand, #TimeScale, #Duration, #TrackVolume, #TrackID, #ImgWidth, #imgHeight, #XResolution, #YResolution, #VideoFrameRate, #MediaCreateDate, #ModifyDate,
#AudioFormat, #AudioChannels, #AudioBits, #AudioSampleRate, #MediaDataSize, #ImageSize, #AvgBitRate, #MIMEType, #CompressorID);
--Adding video extract DATE information
insert into dbo.[Basic Video Meta]([File Directory],[File Size],[File Type],
[File Mod Date],[File Access Date],[File Create Date],[File Permission])
values(#FileDirectory,#FileSize,#FileType,#FileModDate,#FileAccessDate,#FileCreateDate,#FilePermission);
select #id = SCOPE_IDENTITY();
END
So far I have tried moving the method for 'Upload' before the 'Extraction" method thinking that maybe if I insert into the Extraction method first the 'id' would be set and then I wouldn't run into issues once I tried to insert into the database. This just gave me the same "column does not allow nulls" error. I also tried changing how my variables are passed into the methods by changing at what point the 'id' parameter was inserted into the database, this still presented the same result.
Do I need to use some sort of casting, or transaction? and if so do I use this within Dapper and my C# class, or do I need to do this within the stored procedure of my database?

How to make a stored procedure in which the parameters are a list of strings [ SQL Server, ASP.NET Core 3.1 ]

I am creating a website where users can filter the data by brand, storage, price, etc. I want to use a stored procedure to get the data. The problem is that I don't know how to make a stored procedure that accepts a list of strings as parameters.
For example, this is my ASP.NET Core controller:
private readonly contextItem _context;
public ItemsController(contextItem context)
{
_context = context;
}
// GET: api/Items
[HttpGet]
public async Task<ActionResult<IEnumerable<Item>>> GetItem(
string samsung, string iphone, string lg, string _32gb, string _64gb,string _128gb,
string max, string min)
{
List<string> brands = new List<string>(), storage = new List<string>();
string price_min = null, price_max = null;
// brands
if (samsung != null) { brands.Add("samsung"); }
if (iphone != null) { brands.Add("iphone"); }
if (lg != null) { brands.Add("lg"); }
// storage
if (_32gb != null) { storage.Add("32gb"); }
if (_64gb != null) { storage.Add("64gb"); }
if (_128gb != null) { storage.Add("128gb"); }
// price
price_max = max != null ? max : "";
price_min = min != null ? min : "";
string query = $"EXEC SP_Filter #brand ='{string.Join(",", brands)}',#storage='{string.Join(",", storage)}'," +
$"#min='{price_min}',#max='{price_max}'";
return await _context.Item.FromSqlRaw(query).ToListAsync();
}
So the parameters can be more than one, but if they weren't, it would be easy to make a stored procedure like this
create procedure SP_Filter
#brands varchar(250),
#storage varchar(250),
#min decimal,
#max decimal
as
Select *
From Item
Where NAME like '%'+#brands+'%'
and NAME like '%'+#storage+'%'
and PRICE between #min and #max
You can use json or xml. Try this
/* test
DECLARE #Brands nvarchar(4000) SET #Brands = '{"Brands": [{"Brand": "Samsung"}, {"Brand": "iPhone"}, {"Brand": "LG"}, {"Brand": "Xiaomi"}]}';;
DECLARE #Storages nvarchar(4000) SET #Storages = '{"Storages": [{"Storage": "16"}, {"Storage": "32"}, {"Storage": "64"}, {"Storage": "128"}]}';;
SELECT * FROM OPENJSON(#Brands, '$.Brands') WITH ( Brand varchar(20) '$.Brand' );
SELECT * FROM OPENJSON(#Storages, '$.Storages') WITH ( Storage varchar(20) '$.Storage' );
*/
create procedure FilterByBrandStoragePrice
#Brands nvarchar(4000),
#Storages nvarchar(4000),
#min decimal,
#max decimal
as
SELECT *
FROM Item i
WHERE i.Brand in (SELECT * FROM OPENJSON(#Brands, '$.Brands') WITH ( Brand varchar(20) '$.Brand' ))
AND i.Storage in (SELECT * FROM OPENJSON(#Storages, '$.Storages') WITH ( Storage varchar(20) '$.Storage' ))
AND i.PRICE between #min and #max
Here's an example using table value parameters;
CREATE TYPE [TableString] AS TABLE (
Id nvarchar(4000) NULL
)
go
create procedure [name]
#brands [TableString],
...
as
...
public SqlParameter ToSqlParameter(IEnumerable<string> values)
{
var meta = new SqlMetaData("Id", SqlDbType.NVarChar, 4000);
var records = values.Select(v => {
var record = new SqlDataRecord(
meta
);
if (v == null)
record.SetDBNull(0);
else
record.SetString(0, v);
return record;
});
return new SqlParameter()
{
TypeName = "TableString",
SqlDbType = SqlDbType.Structured,
Value = records
};
}
Now you can define that your procedure takes a TableString argument.
You can extend this example slightly, so that you can pass in a TableString into a query;
public class TableValue<T>
{
public T Id { get; set; }
}
public class MyContext : DbContext {
protected override void OnModelCreating(ModelBuilder modelBuilder) {
...
modelBuilder.Entity<TableValue<string>>(e =>
{
e.HasNoKey();
e.ToView("TableString");
e.Property(p => p.Id).HasMaxLength(4000);
});
}
}
var queryable = context.Set<TableValue<string>>()
.FromSqlInterpolated($"select * from {ToSqlParameter( ... )}");

How to check passport number exist or not?

I want to check passport number exist or not ,
before I used this code to check if integer number exist or not ,
but passport number column in MSSQL type varchar(50).
what I tried
1- created stored procedure to read ID No :
create proc [dbo].[VALIDATE_PATIENT_IDNO]
#patient_id varchar(50)
as
select Patient_id from Patients
where Patient_id = #patient_id
2- I created this code in C# to validate id no exist or not :
public int? VALIDATE_PATIENT_IDNO(string patient_id)
{
DAL.DataAccessLayer DAL = new DAL.DataAccessLayer();
DataTable dt = new DataTable();
SqlParameter[] Param = new SqlParameter[1];
Param[0] = new SqlParameter("#patient_id", SqlDbType.VarChar,50);
Param[0].Value = patient_id;
dt = DAL.SelectData("VALIDATE_PATIENT_IDNO", Param);
DAL.close();
if (dt.Rows.Count > 0)
{
DataRow row = dt.Rows[0];
int? patientNumber = row.Field<int>("patient_id");
return patientNumber;
}
// return null otherwise
return null;
}
3- when type the id no or passport no when key down code :
private void textIDNO_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (string.IsNullOrEmpty(textIDNO.Text))
{
txtpcfileno.Focus();
}
else
{
var patientNumber = patient.VALIDATE_PATIENT_IDNO(textIDNO.Text); // int?
bool patientExists = patientNumber.HasValue;
if (patientExists == true)
{
MessageBox.Show("Id or Passport No Exist ", "ID EXIST", MessageBoxButtons.OK, MessageBoxIcon.Stop);
return;
}
else
{
txtpcfileno.Focus();
}
}
}
}
4- I have error appeared in the code in step 2 :
Additional information: Specified cast is not valid.
int? patientNumber = row.Field<int>("patient_id");
How to change the code in step 2 and solve this error and check string value not int? ?
Letting the naming confusions (passportnumber vs patientid) aside, you probably don't want to return the found patientids (because you already know them, as they are part of your selection condition) but the count.
Furthermore, your patientid seems to be a string, yet in your result you try to cast this to an integer. That is not possible, thus the error.
You can try as follows:
create proc [dbo].[VALIDATE_PATIENT_IDNO]
#patient_id varchar(50)
as
select count(Patient_id) as patientcount from Patients
where Patient_id = #patient_id
Assuming that patient_id is the primary key of your table, this will either return 1 if a row with the given id exists or 0 if not.
Then you can do
int? patientNumber = row.Field<int>("patientcount");
and then
bool patientExists = patientNumber > 0;

C# MVC Controller ActionResult query takes a long time to load when there are a lot of records

I have an ActionResult to get Parts that relate to the Vendor Selected. When there is a large amount of parts to get it takes a long time to load. In testing the SQL side it has items that probably do not need to be there. Once removed from the query it is fine and retrieves at a good speed. My question is what in the Controller Code is adding this to the query and slowing it down.
Here is my controller code:
[HttpGet]
public ActionResult Add (Guid id)
{
try
{
var userId = User.Identity.GetUserId();
RFQViewModel r = new RFQViewModel();
GeneralEntities cn = new GeneralEntities();
List<PartsViewModel> Apart = new List<PartsViewModel>();
r.selectedParts = db.VendorsMaterialMap.Where(a => a.VendorId == id).Select(a => a.Material.ToString()).ToArray();
Apart = db.Parts.Where(k => r.selectedParts.Contains(k.Material.ToString())).Select(v => new PartsViewModel
{
Material = v.Material,
PartNumber = v.PartNumber,
VendorReference = v.VendorReference,
PartImage = v.PartImage,
UnitOfMeasure = v.UnitOfMeasure
}).ToList();
r.partitem = Apart;
r.RFQId = Guid.NewGuid();
r.vendor = db.Vendors.Where(d => d.VendorId == id).FirstOrDefault();
var Check = db.RFQs.Where(k => k.VendorId == id).OrderByDescending(K => K.CreatedDate).FirstOrDefault();
if (Check != null)
{
var diff = (System.DateTime.Now - Check.RequestDate).Value;
var days = diff.Days;
if (days < 7)
{
ViewBag.msg = "You already created order for This vendor before... <a href='/RFQ/Details/ " + Check.RFQId + "'>Click here</a>";
}
}
return View(r);
}
catch (Exception ex)
{
throw ex;
}
}
On the SQL side this is the query that is running (I have taken the data out but 1):
SELECT
1 AS [C1],
[Extent1].[Material] AS [Material],
[Extent1].[PartNumber] AS [PartNumber],
[Extent1].[VendorReference] AS [VendorReference],
[Extent1].[PartImage] AS [PartImage],
[Extent1].[UnitOfMeasure] AS [UnitOfMeasure]
FROM [dbo].[Parts] AS [Extent1]
WHERE (LOWER( CAST( [Extent1].[Material] AS nvarchar(max))) IN (N'95647db7-00c4-e911-bb01-001c4208b889'
<---- Other Retrieved Data ------>
)) AND (LOWER( CAST( [Extent1].[Material] AS nvarchar(max))) IS NOT NULL)
If I Remove the LOWER and Change the nvarchar(max) to nvarchar(50). The query comes back fast no matter how many record i pull. So What in the above Controller Code is making a GUID nvarchar(max) and taking it to Lower?
Thanks for your help!

Attach Entity with parameter value null using Entity Framework

So, I'm trying to update rows where LOGIN IS NULL and ID = 1. If there are no rows with these parameters then add new row. I use attach to make that in 1-2 queries so I'm trying to avoid SELECT first and then update.
Problem in NULL value. EF simply ignores LOGIN since it has null value, however I need to find only rows where LOGIN IS NULL. Can I solve that problem without additional SELECT query?
My code:
using (var db = new EntityContext())
{
var ent = new Entity { ID = 1, LOGIN = null };
db.Entities.Attach(ent);
ent.LOGIN = "Whatever";
ent.EMAIL = "Whatever";
int count = db.SaveChanges();
if (count == 0)
{
var clone_ent = new Entity { LOGIN = "Whatever", PASS = "Whatever" };
db.Entities.Add(clone_ent);
db.SaveChanges();
}
}
SQL analog:
UPDATE Entities SET LOGIN = #LOGIN, EMAIL = #EMAIL
WHERE ID = 1 AND LOGIN IS NULL
IF ##ROWCOUNT = 0
INSERT INTO Entities (LOGIN, EMAIL)
VALUES #LOGIN, #EMAIL
Unfortunately, it is not possible to include a WHERE condition into UPDATE statements in entity framework so you will have to select, then update or insert, e.g.:
using (var db = new EntityContext())
{
var ent = db.Entities.Where(x => x.ID == 1 && x.LOGIN == null).FirstOrDefault();
if (ent != null)
{
ent.LOGIN = "Whatever";
ent.EMAIL = "Whatever";
}
else
{
db.Entities.Add(ent);
}
db.SaveChanges();
}

Categories

Resources