Error when collecting multiple resultset from stored procedure - c#

I have a stored procedure which I have written. I am trying to collecting multiple result set from it. But unfortunately I am getting an error
A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll.
The message is the error I keep seeing.
I have tried all I can but don't know were the error is, I have tested my stored procedure it works fine.
Stored procedure:
CREATE PROCEDURE [dbo].[Collectcompanyservicewithpackages]
#CompanyID int
AS
select *
from Serviceduration
where Client_CompanyID = #CompanyID;
select Serviceitem.*
from Serviceduration, Serviceitem
where Client_CompanyID = #CompanyID
and Serviceduration.ServicedurationID = Serviceitem.ServicedurationID;
select ServiceitemPackage.*
from Serviceduration, Serviceitem, ServiceitemPackage
where Client_CompanyID = #CompanyID
and Serviceduration.ServicedurationID = Serviceitem.ServicedurationID
and Serviceitem.ServiceitemID = ServiceitemPackage.ServiceitemID
Database modules:
Snippet
public List<Serviceview> GetFirmServiceswithpackages_sp(int CompanyID)
{
List<Serviceview> allservices = null;
IEnumerable<Serviceduration> servicedurations = null;
IEnumerable<Serviceitem> serviceitems = null;
IEnumerable<ServiceitemPackage> serviceitempackages = null;
using(context){
Debug.WriteLine("App got here for starters .........................");
// If using Code First we need to make sure the model is built before we open the connection
// This isn't required for models created with the EF Designer
//context.Database.Initialize(force: false);
// Create a SQL command to execute the sproc
var cmd = context.Database.Connection.CreateCommand();
cmd.CommandText = "Collectcompanyservicewithpackages #CompanyID";
cmd.CommandType = CommandType.StoredProcedure;
DbParameter inputparameter = new SqlParameter();
inputparameter.DbType = DbType.Int64;
inputparameter.ParameterName = "CompanyID";
inputparameter.Value = CompanyID;
inputparameter.Direction = ParameterDirection.Input;
cmd.Parameters.Add(inputparameter);
try
{
// Run the sproc
context.Database.Connection.Open();
var reader = cmd.ExecuteReader();
// Read Blogs from the first result set
var durations = ((IObjectContextAdapter)context)
.ObjectContext
.Translate<Serviceduration>(reader, "Servicedurations", MergeOption.AppendOnly);
servicedurations = this.Extractdurations(durations);
Debug.WriteLine("No of duration "+servicedurations.Count());
// Move to second result set and read Serviceitems in cart
reader.NextResult();
var services4sale = ((IObjectContextAdapter)context)
.ObjectContext
.Translate<Serviceitem>(reader, "Serviceitems", MergeOption.AppendOnly);
serviceitems = this.Extractservices(services4sale);
Debug.WriteLine("No of services "+serviceitems.Count() );
// Move to second result set and read Serviceitems in cart
reader.NextResult();
var packages = ((IObjectContextAdapter)context)
.ObjectContext
.Translate<ServiceitemPackage>(reader, "ServiceitemPackages", MergeOption.AppendOnly);
serviceitempackages = this.Extractpackages(packages);
Debug.WriteLine("No of packages ...."+ serviceitempackages.Count());
allservices = this.ReturnServiceincart(servicedurations, serviceitems, serviceitempackages);
}
catch(SqlException e){
Debug.WriteLine("Cause of the error "+e.InnerException.Message);
}
finally
{
context.Database.Connection.Close();
}
}
return allservices;
}
//The methods below are used to extract Enumerables from the Object Resultset. I would love to call them helper methods
//This is the help method that would help us to do the final crafting of our stored procedure run around
private List<Serviceview> ReturnServiceincart(IEnumerable<Serviceduration> durations, IEnumerable<Serviceitem> services, IEnumerable<ServiceitemPackage> packages)
{
List<Serviceview> allservices = new List<Serviceview>();
if(services != null){
foreach(var service in services){
Serviceview view = new Serviceview()
{
Name = service.Name,
Cost = service.Cost,
Description = service.Description,
Durationname = durations.Where(item=>item.ServicedurationID == service.ServicedurationID).Select(item=>item.Duration).SingleOrDefault<string>(),
IsVisible = service.IsVisible,
Packages = Returnpackages(service.ServiceitemID, packages) //Note we are not passing service.ServiceitemPackage, cos we are avoiding a lazy loading cos it already been returned in stored procedure.
};
}
}
return allservices;
}
private IEnumerable<Serviceduration> Extractdurations(ObjectResult<Serviceduration> durations)
{
IEnumerable<Serviceduration> servicedurations = durations.AsEnumerable<Serviceduration>();
return servicedurations;
}
private IEnumerable<Serviceitem> Extractservices(ObjectResult<Serviceitem> services4sale)
{
IEnumerable<Serviceitem> serviceitems = services4sale.AsEnumerable<Serviceitem>();
return serviceitems;
}
private IEnumerable<ServiceitemPackage> Extractpackages(ObjectResult<ServiceitemPackage> packages)
{
IEnumerable<ServiceitemPackage> servicepackages = packages.AsEnumerable<ServiceitemPackage>();
return servicepackages;
}
//Because the packages here would contain all packages for all company services we need to filter with a service ID
private List<string> Returnpackages(int ServiceitemID, IEnumerable<ServiceitemPackage> packageitems)
{
List<string> packages = new List<string>();
foreach(var package in packageitems){
if(package.ServiceitemID == ServiceitemID)
packages.Add(package.PackageName);
}
return packages;
}
Changes made below
cmd.CommandText = "Collectcompanyservicewithpackages";
After making a change to the query. I get the error message
The result of the query can not be enumerable more than once.
The new error is on the line
allservices = this.ReturnServiceincart(servicedurations, serviceitems, serviceitempackages);

cmd.CommandText = "Collectcompanyservicewithpackages";
This line solved the magic.
After this I closed the command and the reader object.
It works fine now.

Related

IBM db2Command SQL SELECT * FROM IN #namedParameter

When using the C# code below to construct a DB2 SQL query the result set only has one row. If I manually construct the "IN" predicate inside the cmdTxt string using string.Join(",", ids) then all of the expected rows are returned. How can I return all of the expected rows using the db2Parameter object instead of building the query as a long string to be sent to the server?
public object[] GetResults(int[] ids)
{
var cmdTxt = "SELECT DISTINCT ID,COL2,COL3 FROM TABLE WHERE ID IN ( #ids ) ";
var db2Command = _DB2Connection.CreateCommand();
db2Command.CommandText = cmdTxt;
var db2Parameter = db2Command.CreateParameter();
db2Parameter.ArrayLength = ids.Length;
db2Parameter.DB2Type = DB2Type.DynArray;
db2Parameter.ParameterName = "#ids";
db2Parameter.Value = ids;
db2Command.Parameters.Add(db2Parameter);
var results = ExecuteQuery(db2Command);
return results.ToArray();
}
private object[] ExecuteQuery(DB2Command db2Command)
{
_DB2Connection.Open();
var resultList = new ArrayList();
var results = db2Command.ExecuteReader();
while (results.Read())
{
var values = new object[results.FieldCount];
results.GetValues(values);
resultList.Add(values);
}
results.Close();
_DB2Connection.Close();
return resultList.ToArray();
}
You cannot send in an array as a parameter. You would have to do something to build out a list of parameters, one for each of your values.
e.g.: SELECT DISTINCT ID,COL2,COL3 FROM TABLE WHERE ID IN ( #id1, #id2, ... #idN )
And then add the values to your parameter collection:
cmd.Parameters.Add("#id1", DB2Type.Integer).Value = your_val;
Additionally, there are a few things I would do to improve your code:
Use using statements around your DB2 objects. This will automatically dispose of the objects correctly when they go out of scope. If you don't do this, eventually you will run into errors. This should be done on DB2Connection, DB2Command, DB2Transaction, and DB2Reader objects especially.
I would recommend that you wrap queries in a transaction object, even for selects. With DB2 (and my experience is with z/OS mainframe, here... it might be different for AS/400), it writes one "accounting" record (basically the work that DB2 did) for each transaction. If you don't have an explicit transaction, DB2 will create one for you, and automatically commit after every statement, which adds up to a lot of backend records that could be combined.
My personal opinion would also be to create a .NET class to hold the data that you are getting back from the database. That would make it easier to work with using IntelliSense, among other things (because you would be able to auto-complete the property name, and .NET would know the type of the object). Right now, with the array of objects, if your column order or data type changes, it may be difficult to find/debug those usages throughout your code.
I've included a version of your code that I re-wrote that has some of these changes in it:
public List<ReturnClass> GetResults(int[] ids)
{
using (var conn = new DB2Connection())
{
conn.Open();
using (var trans = conn.BeginTransaction(IsolationLevel.ReadCommitted))
using (var cmd = conn.CreateCommand())
{
cmd.Transaction = trans;
var parms = new List<string>();
var idCount = 0;
foreach (var id in ids)
{
var parm = "#id" + idCount++;
parms.Add(parm);
cmd.Parameters.Add(parm, DB2Type.Integer).Value = id;
}
cmd.CommandText = "SELECT DISTINCT ID,COL2,COL3 FROM TABLE WHERE ID IN ( " + string.Join(",", parms) + " ) ";
var resultList = new List<ReturnClass>();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var values = new ReturnClass();
values.Id = (int)reader["ID"];
values.Col1 = reader["COL1"].ToString();
values.Col2 = reader["COL2"].ToString();
resultList.Add(values);
}
}
return resultList;
}
}
}
public class ReturnClass
{
public int Id;
public string Col1;
public string Col2;
}
Try changing from:
db2Parameter.DB2Type = DB2Type.DynArray;
to:
db2Parameter.DB2Type = DB2Type.Integer;
This is based on the example given here

The procedure "SP_name" has no parameter named "#typ_table" in dapper.net

What I Want.
If user enter duplicated value, then i want to delete that duplicate value and install the new one. I don't want to use update query because of some requirement.
Code:
Web API
public CoCApiResponse CreateVersion(CreateVersion versionObj)
{
var taskForDelete = Task.Run(() =>
versionRepository.DeleteVersions(objVersionCollection));
taskForDelete.Wait();
versionRepository.CreateVersion(versionObj.version, lstVersion).Result;
}
Repository:
public async Task<Version> DeleteVersions(CoCBaseCollection<Version> Versions)
{
List<Version> versionList = new List<Version>();
foreach (var objVersion in Versions)
{
Version version = new Version()
{
Id = objVersion.Id,
VersionName = objVersion.VersionName,
StructureWeek = objVersion.StructureWeek,
IsWLTP = objVersion.IsWLTP,
VersionStatusTypeId = objVersion.VersionStatusTypeId,
CreatedDateTime = System.DateTime.Now,
LastUpdatedDateTime = System.DateTime.Now
};
versionList.Add(version);
}
int retval = 0;
DataTable dtVersions = TableConversion.EnitiesToDataTable<Version>(versionList);
pars = new DynamicParameters();
pars.Add("#VersionTableForDelete", dtVersions.AsTableValuedParameter("dbo.VersionTable"));
pars.Add("#Retval", retval, DbType.Int32, ParameterDirection.Output);
string DeleteVersionSP = "dbo.DeleteVersions";
return await ExecSproc<Version>(DeleteVersionSP, pars, new Version()).ConfigureAwait(false);
}
public async Task<Version> CreateVersion(Version version, List<Version> versions)
{
int retval = 0;
DataTable dtVersions = TableConversion.EnitiesToDataTable<Version>(versions);
pars.Add("#refVersionTable", dtVersions.AsTableValuedParameter("dbo.VersionTable"));
pars.Add("#Retval", retval, DbType.Int32, ParameterDirection.Output);
string CreateVersionSP = "dbo.SPCreateVersion";
return await ExecSproc<Version>(CreateVersionSP, pars, version).ConfigureAwait(false);
}
Problem
I am getting this below error, while I am running the Delete and Create method
The procedure "SPCreateVersion" has no parameter named "#VersionTableForDelete".
What I have tried.
I have checked with my Store Procedure and it's working fine and also searched more than 2 hour from google But I am unable to resolve it. Because no one given the exact solution for dapper.net
Finally, What I found :
Yeah! It is working while doing delete and insert separately
public CoCApiResponse CreateVersion(CreateVersion versionObj)
{
versionRepository.CreateVersion(versionObj.version).Result;// working
}
//
public CoCApiResponse CreateVersion(CreateVersion versionObj)
{
var taskForDelete = Task.Run(() =>
versionRepository.DeleteVersions(versionObj));//working
taskForDelete.Wait();
}
But it is throwing the error while inserting, if we are doing both delete and insert.
public CoCApiResponse CreateVersion(CreateVersion versionObj)
{
var taskForDelete = Task.Run(() =>
versionRepository.DeleteVersions(versionObj));//working
taskForDelete.Wait();
versionRepository.CreateVersion(versionObj.version).Result;// Not Working and throwing an error
}
What I Guess
this error may be related with asyn/sync callback problem. But I don't have any idea to resolve this.
How can we resolve this?
This issue has been resolved while I clear the parameters before adding a new parameters in CreateVersion Store Procedure
like
pars = new DynamicParameters();
Full code is
public async Task<Version> CreateVersion(Version version, List<Version> versions)
{
int retval = 0;
DataTable dtVersions = TableConversion.EnitiesToDataTable<Version>(versions);
pars = new DynamicParameters();// this line resolved the issue
pars.Add("#refVersionTable", dtVersions.AsTableValuedParameter("dbo.VersionTable"));
pars.Add("#Retval", retval, DbType.Int32, ParameterDirection.Output);
string CreateVersionSP = "dbo.SPCreateVersion";
return await ExecSproc<Version>(CreateVersionSP, pars, version).ConfigureAwait(false);
}

Insert data into database using LINQ

I wrote a very simple method. It saves data from class DayWeather to the database. Method checks if line with that day exist in table and update her or create a new line.
I am doing it by adding new class for LINQ and move table from Server Inspector to the constructor. It generate new class WeatherTBL.
Method itself looks like this:
public static void SaveDayWeather(DayWeather day)
{
using (DataClassesDataContext db = new DataClassesDataContext())
{
var existingDay =
(from d in db.WeatherTBL
where d.DateTime.ToString() == day.Date.ToString()
select d).SingleOrDefault<WeatherTBL>();
if (existingDay != null)
{
existingDay.Temp = day.Temp;
existingDay.WindSpeed = day.WindSpeed;
existingDay.Pressure = day.Pressure;
existingDay.Humidity = day.Humidity;
existingDay.Cloudiness = day.Cloudiness;
existingDay.TypeRecip = day.TypeRecip;
db.SubmitChanges();
}
else
{
WeatherTBL newDay = new WeatherTBL();
newDay.DateTime = day.Date;
newDay.Temp = day.Temp;
newDay.WindSpeed = day.WindSpeed;
newDay.Pressure = day.Pressure;
newDay.Humidity = day.Humidity;
newDay.Cloudiness = day.Cloudiness;
newDay.TypeRecip = day.TypeRecip;
db.WeatherTBL.InsertOnSubmit(newDay);
db.SubmitChanges();
}
}
}
When I tried to call him from UnitTest project:
[TestMethod]
public void TestDataAccess()
{
DayWeather day = new DayWeather(DateTime.Now);
DataAccessClass.SaveDayWeather(day);
}
It write, that test has passed successfully. But if look into table, it has`t chanched.
No error messages shows. Does anyone know whats the problem?
P.S. Sorry for my bad English.
UDP
Problem was in that:
"...db maybe copied to the debug or release folder at every build, overwriting your modified one". Thanks #Silvermind
I wrote simple method to save employee details into Database.
private void AddNewEmployee()
{
using (DataContext objDataContext = new DataContext())
{
Employee objEmp = new Employee();
// fields to be insert
objEmp.EmployeeName = "John";
objEmp.EmployeeAge = 21;
objEmp.EmployeeDesc = "Designer";
objEmp.EmployeeAddress = "Northampton";
objDataContext.Employees.InsertOnSubmit(objEmp);
// executes the commands to implement the changes to the database
objDataContext.SubmitChanges();
}
}
Please try with lambda expression. In your code, var existingDay is of type IQueryable
In order to insert or update, you need a variable var existingDay of WeatherTBL type.
Hence try using below..
var existingDay =
db.WeatherTBL.SingleOrDefault(d => d.DateTime.Equals(day.Date.ToString()));
if(existingDay != null)
{
//so on...
}
Hope it should work..
Linq to SQL
Detail tc = new Detail();
tc.Name = txtName.Text;
tc.Contact = "92"+txtMobile.Text;
tc.Segment = txtSegment.Text;
var datetime = DateTime.Now;
tc.Datetime = datetime;
tc.RaisedBy = Global.Username;
dc.Details.InsertOnSubmit(tc);
try
{
dc.SubmitChanges();
MessageBox.Show("Record inserted successfully!");
txtName.Text = "";
txtSegment.Text = "";
txtMobile.Text = "";
}
catch (Exception ex)
{
MessageBox.Show("Record inserted Failed!");
}

Convert Function Based on TSQL with Function Based with Entity Framework

I have two functions that each return the same list of objects. But, the one that uses TSQL is much faster than the one using Entity Framework and I do not understand why one would be faster than the other. Is it possible to modify my EF function to work as fast as the TSQL one?
Any help will be appreciated. My code is below:
TSQL:
public static List<ChartHist> ListHistory_PureSQL()
{
List<DataRow> listDataRow = null;
string srtQry = #"Select LoginHistoryID,
LoginDuration as LoginDuration_Pass,
0 as LoginDuration_Fail,
LoginDateTime,
LoginLocationID,
LoginUserEmailID,
LoginApplicationID,
LoginEnvironmentID,
ScriptFrequency,
LoginStatus,
Reason
From LoginHistory
Where LoginStatus = 'Pass'
UNION
Select LoginHistoryID,
0 as LoginDuration_Pass,
LoginDuration as LoginDuration_Fail,
LoginDateTime,
LoginLocationID,
LoginUserEmailID,
LoginApplicationID,
LoginEnvironmentID,
ScriptFrequency,
LoginStatus,
Reason
From LoginHistory
Where LoginStatus = 'Fail'";
using (SqlConnection conn = new SqlConnection(Settings.ConnectionString))
{
using (SqlCommand objCommand = new SqlCommand(srtQry, conn))
{
objCommand.CommandType = CommandType.Text;
DataTable dt = new DataTable();
SqlDataAdapter adp = new SqlDataAdapter(objCommand);
conn.Open();
adp.Fill(dt);
if (dt != null)
{
listDataRow = dt.AsEnumerable().ToList();
}
}
}
var listChartHist = (from p in listDataRow
select new ChartHist
{
LoginHistoryID = p.Field<Int32>("LoginHistoryID"),
LoginDuration_Pass = p.Field<Int32>("LoginDuration_Pass"),
LoginDuration_Fail = p.Field<Int32>("LoginDuration_Fail"),
LoginDateTime = p.Field<DateTime>("LoginDateTime"),
LoginLocationID = p.Field<Int32>("LoginLocationID"),
LoginUserEmailID = p.Field<Int32>("LoginUserEmailID"),
LoginApplicationID = p.Field<Int32>("LoginApplicationID"),
LoginEnvironmentID = p.Field<Int32>("LoginEnvironmentID"),
ScriptFrequency = p.Field<Int32>("ScriptFrequency"),
LoginStatus = p.Field<String>("LoginStatus"),
Reason = p.Field<String>("Reason")
}).ToList();
return listChartHist;
}
EF:
public static List<ChartHist> ListHistory()
{
using (var db = new LatencyDBContext())
{
var loginHist = (from hist in db.LoginHistories
select new { LoginHistory = hist }).ToList();
//PUT LOGIN HISTORY RECORDS INTO A LOCAL LIST
var listHistory = new List<ChartHist>();
foreach (var item in loginHist)
{
var localHistData = new ChartHist();
localHistData.LoginHistoryID = item.LoginHistory.LoginHistoryID;
//split up the duration for pass and fail values
if (item.LoginHistory.LoginStatus.ToUpper() == "PASS")
{
localHistData.LoginDuration_Pass = Convert.ToDouble(item.LoginHistory.LoginDuration);
localHistData.LoginDuration_Fail = 0;
}
else if (item.LoginHistory.LoginStatus.ToUpper() == "FAIL")
{
localHistData.LoginDuration_Pass = 0;
localHistData.LoginDuration_Fail = Convert.ToDouble(item.LoginHistory.LoginDuration);
}
localHistData.LoginDateTime = item.LoginHistory.LoginDateTime;
localHistData.LoginLocationID = item.LoginHistory.LoginLocationID;
localHistData.LoginUserEmailID = item.LoginHistory.LoginUserEmailID;
localHistData.LoginApplicationID = item.LoginHistory.LoginApplicationID;
localHistData.LoginEnvironmentID = item.LoginHistory.LoginEnvironmentID;
localHistData.LoginStatus = item.LoginHistory.LoginStatus;
localHistData.Reason = item.LoginHistory.Reason;
localHistData.ScriptFrequency = item.LoginHistory.ScriptFrequency;
listHistory.Add(localHistData);
}
return listHistory;
}
}
Of course EF will take longer to execute than a plain old SQL query, and there's very little that you can do about it (except write the most optimal LINQ queries that you can).
There's a very simple reason why this is so. Running a direct SQL command will just send back the data, with no muss and no fuss attached to it, waiting for you to do the data manipulations to get it to the point where it fits nicely into whatever data structure you want it in. Running EF, on the other hand, means that not only does it run the SQL command, but it massages the data for you into objects that you can manipulate right away. That extra action of going through ADO.NET and converting the data into the objects automatically means that it will take longer than just doing the plain SQL query.
On the flip side of that coin, however, EF does provide a very nice and simple way to debug and solve whatever problems you might have from a specific query/function (like by any exceptions thrown).
I can't performance test this, but try this solution instead before you remove EF entirely:
var loginHist = db.LoginHistories.Where(item => item.LoginStatus.ToUpper() == "PASS" || item.LoginStatus.ToUpper() == "FAIL")
.Select(item => new ChartHist()
{
LoginHistoryID = item.LoginHistoryID,
LoginDuration_Pass = item.LoginStatus.ToUpper() == "PASS" ? Convert.ToDouble(item.LoginDuration) : 0,
LoginDuration_Fail = item.LoginStatus.ToUpper() == "FAIL" ? Convert.ToDouble(item.LoginDuration) : 0,
LoginDateTime = item.LoginDateTime,
LoginLocationID = item.LoginLocationID,
LoginUserEmailID = item.LoginUserEmailID,
LoginApplicationID = item.LoginApplicationID,
LoginEnvironmentID = item.LoginEnvironmentID,
LoginStatus = item.LoginStatus,
Reason = item.Reason,
ScriptFrequency = item.ScriptFrequency,
});
return loginHist.ToList();
This is the "correct" way to populate a new object from a select. It will only retrieve the data you care about, and will put it directly into the object, rather than converting it into an object and then converting it again, from one object to another.
Note: I prefer the functional calls to the from / select form, but it'd be correct either way.

How to move records from one table to another in linq

I have a ProductLevel table in an SQL database. It contains the products for a store. I want to copy these records into a ProductLevelDaily table at the time the user logs onto the hand held device in the morning.
As they scan items the bool goes from false to true so at anytime they can see what items are left to scan/check.
From the mobile device I pass the siteID and date to the server:
int userID = int.Parse(oWebRequest.requestData[5]); and a few other things
IEnumerable<dProductLevelDaily> plditems
= DSOLDAL.CheckProductDailyLevelbySiteCount(siteID, currentDate);
This checks if there are any records already moved into this table for this store. Being the first time this table should be empty or contain no records for this store on this date.
if (plditems.Count() == 0) // is 0
{
IEnumerable<dProductLevel> ppitems = DSOLDAL.GetProductsbySite(siteID);
// this gets the products for this store
if (ppitems.Count() > 0)
{
dProduct pi = new dProduct();
foreach (dProductLevel pl in ppitems)
{
// get the product
pi = DSOLDAL.getProductByID(pl.productID, companyID);
dProductLevelDaily pld = new dProductLevelDaily();
pld.guid = Guid.NewGuid();
pld.siteID = siteID;
pld.statusID = 1;
pld.companyID = companyID;
pld.counted = false;
pld.createDate = DateTime.Now;
pld.createUser = userID;
pld.productID = pl.productID;
pld.name = "1000"; // pi.name;
pld.description = "desc"; // pi.description;
DSOLDAL.insertProductLevelDailyBySite(pld);
}
}
}
On the PDA the weberequest response returns NULL
I can't see what the problem is and why it wont work.
The insert is in DSOLDAL:
public static void insertProductLevelDailyBySite(dProductLevelDaily pld)
{
dSOLDataContext dc = new dSOLDataContext();
try
{
dc.dProductLevelDailies.InsertOnSubmit(pld);
// dProductLevelDailies.Attach(pld, true);
dc.SubmitChanges();
}
catch (Exception exc)
{
throw new Exception(getExceptionMessage(exc.Message));
}
finally
{
dc = null;
}
}
This code works until I put the foreach loop inside with the insert
IEnumerable<dProductLevelDaily> plditems
= DSOLDAL.CheckProductDailyLevelbySiteCount(siteID, s);
if (plditems.Count() == 0) // plditems.Count() < 0)
{
IEnumerable<dProductLevel> ppitems = DSOLDAL.GetProductsbySite(siteID);
if (ppitems.Count() > 0)
{
oWebResponse.count = ppitems.Count().ToString();
oWebResponse.status = "OK";
}
else
{
oWebResponse.count = ppitems.Count().ToString();
oWebResponse.status = "OK";
}
}
else
{
oWebResponse.count = "2"; // plditems.Count().ToString();
oWebResponse.status = "OK";
}
These kind of bulk operations aren't very well matched to what Linq-to-SQL does.
In my opinion, I'd do this using a stored procedure, which you could include in your Linq-to-SQL DataContext and call from there.
That would also leave the data on the server and just copy it from one table to the other, instead of pulling down all data to your client and re-uploading it to the server.
Linq-to-SQL is a great tool - for manipulating single objects or small sets. It's less well suited for bulk operations.

Categories