Delete a sql row using Linq in C# - c#

I am trying to delete a sql table record from C# thru Linq but some reason DeleteonSubmit is not recoganized,am not sure what iam missing here, please guide me the right way
here is my code
proxy = new ServiceClient("basicHttp_IService");
//GatewayService.ServiceClient proxy = new ServiceClient("basicHttp_IService");
SearchCriteria criteria = new SearchCriteria();
criteria.UserRoles = new string[] { "*" };
var stories = proxy.GetStoryItemsByCriteria(criteria);
var programs = proxy.GetPrograms();
var Profiles = proxy.GetProfiles();
foreach(StoryProgram sp in lstStoriestoClose)
{
try
{
DateTime LastUpdateTimestamp;
DateTime CurrentTime = DateTime.Now;
LastUpdateTimestamp = sp.Story.LastUpdatedOn;
if ((CurrentTime - LastUpdateTimestamp).TotalHours > 24)
{
//Delete the story from database
var storytoDelete = from story in stories
where story.Id == sp.Story.Id
select story;
//I am trying to delete the record like below
stories.DeleteonSubmit(storytoDelete);
stories.SubmitChanges();
//Intellisense doesn't show the option DeleteonSubmit and SubmitChanges
}
}
}
Please guide me the right way to delete the record in SQL thru Linq

DeleteOnSubmit is for single entities. Your query returns a collection of entities (granted there may be only one entry, but it's still a collection). You can either use DeleteAllOnSubmit:
//Delete the story from database
var storytoDelete = from story in stories
where story.Id == sp.Story.Id
select story;
//I am trying to delete the record like below
stories.DeleteAllOnSubmit(storytoDelete);
or explicitly extract one record:
//Delete the story from database
var storytoDelete = from story in stories
where story.Id == sp.Story.Id
select story;
//I am trying to delete the record like below
stories.DeleteOnSubmit(storytoDelete.Single()); // or First, depending on whether you expect more than one match

It looks like your service is returning an array and not a valid linq database object. This is why it does not recognize the methods you expect to see. You need to examine the type and go from there.
You can always right click the service reference and configure to check/set the return type.

I just added delete functionality in WCF service and pass the sql record details to delete the record from SQL that solved my problem.
Thanks all for the suggestion and advise.
foreach(StoryProgram sp in lstStoriestoClose)
{
try
{
DateTime LastUpdateTimestamp;
DateTime CurrentTime = DateTime.Now;
LastUpdateTimestamp = sp.Story.LastUpdatedOn;
if ((CurrentTime - LastUpdateTimestamp).TotalHours > 24)
{
//Delete the story from database
//Check the gateway to delete the record in the db.
var storytoDelete= from story in stories
where story.Id== sp.Story.Id
select story;
// stories.DeleteAllonSubmit(storytoDelete);
List<StoryProgram> lstStoriestoDelete = (from story in storytoDelete
join program in programs on story.ProgramId equals program.Id
join profile in Profiles on story.ProfileId equals profile.Id
select new StoryProgram(story, program, profile)).ToList();
foreach (StoryProgram sps in lstStoriestoDelete)
{
try
{
proxy.DeleteStoryItem(sps.Story.Id);
}

Related

Speeding up a linq query with 40,000 rows

In my service, first I generate 40,000 possible combinations of home and host countries, like so (clientLocations contains 200 records, so 200 x 200 is 40,000):
foreach (var homeLocation in clientLocations)
{
foreach (var hostLocation in clientLocations)
{
allLocationCombinations.Add(new AirShipmentRate
{
HomeCountryId = homeLocation.CountryId,
HomeCountry = homeLocation.CountryName,
HostCountryId = hostLocation.CountryId,
HostCountry = hostLocation.CountryName,
HomeLocationId = homeLocation.LocationId,
HomeLocation = homeLocation.LocationName,
HostLocationId = hostLocation.LocationId,
HostLocation = hostLocation.LocationName,
});
}
}
Then, I run the following query to find existing rates for the locations above, but also include empty the missing rates; resulting in a complete recordset of 40,000 rows.
var allLocationRates = (from l in allLocationCombinations
join r in Db.PaymentRates_AirShipment
on new { home = l.HomeLocationId, host = l.HostLocationId }
equals new { home = r.HomeLocationId, host = (Guid?)r.HostLocationId }
into matches
from rate in matches.DefaultIfEmpty(new PaymentRates_AirShipment
{
Id = Guid.NewGuid()
})
select new AirShipmentRate
{
Id = rate.Id,
HomeCountry = l.HomeCountry,
HomeCountryId = l.HomeCountryId,
HomeLocation = l.HomeLocation,
HomeLocationId = l.HomeLocationId,
HostCountry = l.HostCountry,
HostCountryId = l.HostCountryId,
HostLocation = l.HostLocation,
HostLocationId = l.HostLocationId,
AssigneeAirShipmentPlusInsurance = rate.AssigneeAirShipmentPlusInsurance,
DependentAirShipmentPlusInsurance = rate.DependentAirShipmentPlusInsurance,
SmallContainerPlusInsurance = rate.SmallContainerPlusInsurance,
LargeContainerPlusInsurance = rate.LargeContainerPlusInsurance,
CurrencyId = rate.RateCurrencyId
});
I have tried using .AsEnumerable() and .AsNoTracking() and that has sped things up quite a bit. The following code shaves several seconds off of my query:
var allLocationRates = (from l in allLocationCombinations.AsEnumerable()
join r in Db.PaymentRates_AirShipment.AsNoTracking()
But, I am wondering: How can I speed this up even more?
Edit: Can't replicate foreach functionality in linq.
allLocationCombinations = (from homeLocation in clientLocations
from hostLocation in clientLocations
select new AirShipmentRate
{
HomeCountryId = homeLocation.CountryId,
HomeCountry = homeLocation.CountryName,
HostCountryId = hostLocation.CountryId,
HostCountry = hostLocation.CountryName,
HomeLocationId = homeLocation.LocationId,
HomeLocation = homeLocation.LocationName,
HostLocationId = hostLocation.LocationId,
HostLocation = hostLocation.LocationName
});
I get an error on from hostLocation in clientLocations which says "cannot convert type IEnumerable to Generic.List."
The fastest way to query a database is to use the power of the database engine itself.
While Linq is a fantastic technology to use, it still generates a select statement out of the Linq query, and runs this query against the database.
Your best bet is to create a database View, or a stored procedure.
Views and stored procedures can easily be integrated into Linq.
Material Views ( in MS SQL ) can further speed up execution, and missing indexes are by far the most effective tool in speeding up database queries.
How can I speed this up even more?
Optimizing is a bitch.
Your code looks fine to me. Make sure to set the index on your DB schema where it's appropriate. And as already mentioned: Run your Linq against SQL to get a better idea of the performance.
Well, but how to improve performance anyway?
You may want to have a glance at the following link:
10 tips to improve LINQ to SQL Performance
To me, probably the most important points listed (in the link above):
Retrieve Only the Number of Records You Need
Turn off ObjectTrackingEnabled Property of Data Context If Not
Necessary
Filter Data Down to What You Need Using DataLoadOptions.AssociateWith
Use compiled queries when it's needed (please be careful with that one...)

Linq to SQL fetching cached results

when I select objects using Linq, i seem to get cached results at first.
I use the following code to fetch an applicant from the DB on GET requests assume that this data is STATE_1
using (AdmissionsAppEntities db = new AdmissionsAppEntities())
{
// Fetch the user
ApplicationData applicant = (from a in db.ApplicationDatas
where a.userGUID == userGUID
select a).SingleOrDefault();
}
and the following code to save changes against this record on POST requests, after the SaveChanges is called this record should be in STATE_2
using (AdmissionsAppEntities db = new AdmissionsAppEntities())
{
// Fetch the user
var applicant = (from a in db.ApplicationDatas
where a.userGUID == userGUID
select a).SingleOrDefault();
if (applicant != null)
{
// Save page 1 data
...
applicant.lastUpdate = DateTime.Now;
db.Entry(applicant).State = EntityState.Modified;
DataBag.result = db.Entry(applicant).GetValidationResult();
if (DataBag.result.ValidationErrors.Count == 0)
{
db.SaveChanges();
}
}
}
if (DataBag.result.ValidationErrors.Count == 0)
{
return RedirectToAction("PageTwo");
}
The database properly saves STATE_2 (i can see it in the db if I use a sql inspection tool), but on subsequent pageload, STATE_1 is retrieved.
I see tons of results where people are having this issue, but no ideas on how to fix it.
UPDATE 1
I moved the RedirectToAction calls (all my returns) to outside the using block to make sure that each DbContext's Destroy function gets called. Did not appear to solve the problem.
People are actually having this issue, so I'm going to leave this up, my issue ended up being Orchard CMS caching my module's pages.

Linq to Sql General Help - Insert Statement

I am currently trying to create a new order (which will be shown below) in a web service, and then send that data to insert a new row into the database. For some reason my DBML / Data Context does not allow me to use InsertOnSubmit.
Any ideas? I haven't used Linq to Sql in about 7 months.
Thanks in advance.
[WebMethod]
public string InsertOrderToDatabases()
{
//Start Data Contexts ------
DataContext db = new DataContext(System.Configuration.ConfigurationManager.AppSettings["RainbowCMSConnectionString"]);
DataContext dcSqlOES = new DataContext(System.Configuration.ConfigurationManager.AppSettings["OESConnectionString"]);
//Get table from local database
Table<Schedule> Schedule = db.GetTable<Schedule>();
//Find last order number in databases
var lastOrderNumber = from lOrder in Schedule
orderby lOrder.templ_idn descending
select lOrder.templ_idn;
int firstOrderID;
var firstOrder = lastOrderNumber.FirstOrDefault();
firstOrderID = firstOrder.Value + 1;
qrOrder qrOrd = new qrOrder
{
.... data in here creating a new order
};
//TODO: fix below with an insert on submit
if (qrOrd != null)
{
// **Schedule.InsertOnSubmit(qrOrd);**
}
//db.GetTable<Schedule>().InsertOnSubmit(qrOrd);
try
{
//Submit the changes to the database
db.SubmitChanges();
return "Orders were sent to the databases.";
}
catch ()
{
}
}
Based on your response, it appears that you are using the wrong table, or perhaps the wrong data type. I also noticed that when you declare your localSchedule variable, you declare it as type Table<Schedule>, which means it should contain Schedule entities, not qrOrder entities.
Table<TEntity>.InsertOnSubmit expects a specific strongly typed entity to be passed in. In your case, it is expecting Web_Service.Schedul‌e, but you are trying to pass in a qrOrder.
Schedule.InsertOnSubmit(qrOrd);
That line will not treat to submit changes to connected entity , Try this
db.Schedule.InsertOnSubmit(qrOrd);
db.SubmitChanges();
you can try with
db.GetTable(typeof(Schedule)).InsertOnSubmit(qrOrd);
Or
db.GetTable(qrOrd.GetType()).InsertOnSubmit(qrOrd);

Do not find DeleteOnSubmit method

Im want to delete rows from a table that in my data base.
i have the member
private static WeightScaleEntities Weight = new Weight();
this member contains my database. in the data base i have table: User_Activity.
I want to delete rows from user activity by given i_UserActivityId, as follow:
//Get the rows for delete
var deleteUserActivities = from details in Weight.User_Activity
where details.Id == i_UserActivityId
select details;
Now i want to delete this rows, so i tried to do:
foreach (var item in deleteUserActivities)
{
m_WeightScaleEntities.User_Activity.*
}
and i dont get the method DeleteOnSubmit!
Why?
there is another option???
User_Activity.*: is that a typo?
What I think you want is:
foreach (var item in deleteUserActivities)
{
Weight.DeleteObject(item);
}
And then SaveChanges() on the object context.
BTW, a static object context is not a good idea. You should carefully control the life cycle of object contexts.
There is more than one way to execute deletion in Entity Framework,
You must take into account what are the values that you want to delete? one Row or more.
when you need to delete on Row from table we can use these ways:
// first way
using (WeightScaleEntities db = new WeightScaleEntities())
{
var deleteUserActivities = from details in db.User_Activity
where details.Id == i_UserActivityId
select details;
if (deleteUserActivities.Count() > 0)
{
db.deleteUserActivities.Remove(deleteUserActivities.First());
db.SaveChanges();
}
}
this line deleteUserActivities.Count()>0 to check if you have result in the Query or not.
and this deleteUserActivities.First() if the query return set of rows delete the first. "to make the process more secure if you don't know about the data in the table"
// second way
using (WeightScaleEntities db = new WeightScaleEntities())
{
var deleteUserActivities = (from details in db.User_Activity
where details.Id == i_UserActivityId
select details).SingleOrDefault();
if (deleteUserActivities != null)
{
db.User_Activity.Remove(deleteUserActivities);
// or use this line
//db.Entry(deleteUserActivities).State = System.Data.Entity.EntityState.Deleted;
db.SaveChanges();
}
}
You can also use Single or SingleOrDefault to get a single object. Single or SingleOrDefault will throw an exception, if the result contains more than one element. Use Single or SingleOrDefault where you are sure that the result would contain only one element. If the result has multiple elements then there must be some problem.
Also, if you need to remove one or multi rows use this way:
using (WeightScaleEntities db = new WeightScaleEntities())
{
var deleteUserActivities = (from details in db.User_Activity
where details.Id == i_UserActivityId
select details).ToList<User_Activity>(); //<User_Activity> her name of your DbSet
foreach(deleteObject in deleteUserActivities)
{
db.Entry(deleteObject).State = System.Data.Entity.EntityState.Deleted;
}
db.SaveChanges();
}
Best Regards
and sorry about English language.
using(WeightScaleEntities db=new WeightScaleEntities())
{
var deleteUserActivities = from details in db.User_Activity
where details.Id == i_UserActivityId
select details;
if (deleteUserActivities.Count()>0)
{
db.deleteUserActivities.Remove(deleteUserActivities.First());
db.SaveChanges();
}
}

bulk insert and update with ADO.NET Entity Framework

I am writing a small application that does a lot of feed processing. I want to use LINQ EF for this as speed is not an issue, it is a single user app and, in the end, will only be used once a month.
My questions revolves around the best way to do bulk inserts using LINQ EF.
After parsing the incoming data stream I end up with a List of values. Since the end user may end up trying to import some duplicate data I would like to "clean" the data during insert rather than reading all the records, doing a for loop, rejecting records, then finally importing the remainder.
This is what I am currently doing:
DateTime minDate = dataTransferObject.Min(c => c.DoorOpen);
DateTime maxDate = dataTransferObject.Max(c => c.DoorOpen);
using (LabUseEntities myEntities = new LabUseEntities())
{
var recCheck = myEntities.ImportDoorAccess.Where(a => a.DoorOpen >= minDate && a.DoorOpen <= maxDate).ToList();
if (recCheck.Count > 0)
{
foreach (ImportDoorAccess ida in recCheck)
{
DoorAudit da = dataTransferObject.Where(a => a.DoorOpen == ida.DoorOpen && a.CardNumber == ida.CardNumber).First();
if (da != null)
da.DoInsert = false;
}
}
ImportDoorAccess newIDA;
foreach (DoorAudit newDoorAudit in dataTransferObject)
{
if (newDoorAudit.DoInsert)
{
newIDA = new ImportDoorAccess
{
CardNumber = newDoorAudit.CardNumber,
Door = newDoorAudit.Door,
DoorOpen = newDoorAudit.DoorOpen,
Imported = newDoorAudit.Imported,
RawData = newDoorAudit.RawData,
UserName = newDoorAudit.UserName
};
myEntities.AddToImportDoorAccess(newIDA);
}
}
myEntities.SaveChanges();
}
I am also getting this error:
System.Data.UpdateException was unhandled
Message="Unable to update the EntitySet 'ImportDoorAccess' because it has a DefiningQuery and no element exists in the element to support the current operation."
Source="System.Data.SqlServerCe.Entity"
What am I doing wrong?
Any pointers are welcome.
You can do multiple inserts this way.
I've seen the exception you're getting in cases where the model (EDMX) is not set up correctly. You either don't have a primary key (EntityKey in EF terms) on that table, or the designer has tried to guess what the EntityKey should be. In the latter case, you'll see two or more properties in the EDM Designer with keys next to them.
Make sure the ImportDoorAccess table has a single primary key and refresh the model.

Categories

Resources