Loop to delete multiple items in list...c# - c#

I have a method that searches a database for all the customers with the same company name and then returns a list of their ID numbers and for now I have them being saved to a text file so I can confirm that it worked.
The problem I am having though, is accessing that list of ID numbers and going back and deleting them. In the following code I use a request that will cancel a customer by their ID number. I use a foreach loop that was supposed to get the list of ID's and delete them all but instead it just deletes one and not a different one each time, it deletes the same one each time, rather attempts to, I just get the exception back saying you are trying to delete a customer that was already deleted. Please send any suggestions on what I am doing wrong!
SearchRequest _request;
CancelRequest _request2;
SearchResponse _response;
CancelResponse _response2;
public void ArrangeRequest() {
_request=new CustomerSearchRequest();
_request.Company="Test Inc. ";
}
var customerIds=_response.Customers.Select(c => c.CustID).ToList();
foreach(var custID in customerIds) {
_request2=new CancelRequest();
_request2.CustID=custID;
_request2.Company=_request.Company;
}
public void Response() {
var ws=new RunEngine();
_response=ws.SearchCust(new AppHeader(), _request) as SearchResponse;
_response2=ws.CancelCust(new AppHeader(), _request2) as CancelResponse;
}

You are reusing _request2 field. Instead of storing single cancel request in field, use list of requests:
List<CancelRequest> _cancelRequests;
Then create and add all requests to this list:
var customerIds = _response.Customers.Select(c => c.CustID);
_cancelRequests = customerIds.Select(custID => new CancelRequest {
CustID = custID,
Company = _request.Company
}).ToList();
And process those requests one by one later.

Seems your issue doesn't happen directly with list, because your CancelCust can take one Request at a time. I actually cannot understand where the earliest code fragment you post should be, so I just name it NowhereMethod!
I've also revised for your code, corrected something like _request.Company=_request.Company;. I further deduced all your class hierarchy from the usage according to the code you've post.
As you stated, the deletion is done by CancelRequest, however, as I mentioned above, it can only take one Request at a time, and the Request is inferred that it saves the information only about one customer. Thus, I'm thinking that your issue can simply solve by rewriting the Response method.
You can still think the problem is about to make them a list like other answers shown that, those are correct way to use Linq. Nevertheless, you might need to decide for a correct place to put in some class, and either design a method in a correct way to take the list.
So, it's the code, I deduced and tried to correct; note that I use fields instead of those probably are properties, and put only those are needed.
You might want to take a look of the comments in the code.
partial class Listener /* I named it, to put your code */ {
SearchRequest _request;
CancelRequest _request2;
SearchResponse _response;
CancelResponse _response2;
public void ArrangeRequest() {
_request=new CustomerSearchRequest();
_request.Company="Test Inc. ";
}
void NowhereMethod() {
var customerIds=_response.Customers.Select(c => c.CustID).ToList();
foreach(var custID in customerIds) {
_request2=new CancelRequest();
_request2.CustID=custID;
_request2.Company=_request.Company;
}
}
public void ResponseOriginal() {
var ws=new RunEngine();
_response=ws.SearchCust(new AppHeader(), _request) as SearchResponse;
_response2=ws.CancelCust(new AppHeader(), _request2) as CancelResponse;
}
public void Response() /* tried to correct */ {
var ws=new RunEngine();
_response=ws.SearchCust(new AppHeader(), _request) as SearchResponse;
var customerIds=_response.Customers.Select(c => c.CustID).ToList();
foreach(var custID in customerIds) {
_request2=new CancelRequest();
_request2.CustID=custID;
_request2.Company=_request.Company;
// Seems it should be like this
// but note the assignment might be wrong, it's according to what `CancelCust` returns
// for the correct way to make it a list of Customer is appeared in other answers
_response2=ws.CancelCust(new AppHeader(), _request2) as CancelResponse;
}
}
}
partial class Customer {
public String CustID;
}
partial class Response {
public List<Customer> Customers;
}
partial class Request {
public String Company;
public String CustID;
}
partial class SearchResponse: Response {
}
partial class CancelResponse: Response {
}
partial class SearchRequest: Request {
}
partial class CancelRequest: Request {
}
partial class CustomerSearchRequest: SearchRequest {
}
partial class AppHeader {
}
partial class RunEngine {
public Response SearchCust(AppHeader appHelper, Request request) {
// I don't know what it's like
throw new NotImplementedException();
}
public Response CancelCust(AppHeader appHelper, Request request) {
// I don't know what it's like
throw new NotImplementedException();
}
}
The Request and Customer can either be declared as
partial class Customer {
// Company was not appearing used in the code
public String CustID;
}
partial class Request {
public String Company;
public String CustID;
}
or
partial class Customer {
public String Company;
public String CustID;
}
partial class Request: Customer {
}
will not break the code.

_request appears to be a lone variable, and not a list. It would then only do one record since you're newing it up every single time through the loop and not storing any previous loop values in a list.
Edit: You'd want to do something like this:
var requestList = new List<CancelRequest>();
var customerIds = _response.Customers.Select(c => c.CustID).ToList();
foreach (var custID in customerIds)
{
_request = new CancelRequest();
_request.CustID = custID;
_request.Company = _request.Company;
requestList.Add(_request);
}

Related

ASP.NET MVC - Best practices when passing dependencies

I have a question, that I tried to Google but honestly, I don't really know how to search or even ask this particular question.
Let's imagine I have the following:
Controller
[HttpGet]
public virtual ActionResult Summary()
{
var summaryViewModel = new CheckoutSummaryViewModel()
{
Products = ProductViewModel.BuildListFromShoppingCart(GetShoppingCart())
};
return View("_Summary", summaryViewModel);
}
ProductViewModel
public class ProductViewModel
{
public string Name
{
get; set;
}
public static List<ProdutoCheckoutViewModel> BuildListFromShoppingCart(ShoppingCart shoppingCart, IMappingService mappingService)
{
var itemsInCart = new List<ProductViewModel>();
foreach (var item in shoppingCart.ItemsInCart)
{
var itemViewModel = mappingService.Map<Product, ProductViewModel>(item.Product);
itemViewModel.Quantidade = item.Quantity;
itemsInCart.Add(itemViewModel);
}
return itemsInCart;
}
}
This is not production code. Is just so I can explain what I mean.
Is this the correct way of doing this?
Is there a better way than using static for building the list? I really don't want to do it inside the controller.
Passing IMappingService to the method does not look right. But maybe I'm just being picky. Is it the best way?
Another case, where I need to pass Session State to a static helper class.
public static Guid GetCheckoutId(HttpSessionStateBase session)
{
return (Guid)session["checkoutId"];
}
Or, also, sometimes I need to pass as parameter, to helper methods, my "unifOfWork", since I use the repository pattern.
I've come accross this "problem" a lot and I did not find the best way, yet, to do it.
PS: If any of you has a better title for this question, please tell me so I can update it.
Controller
If you use DI, it would look something like this:
public class CheckoutController
{
private readonly ICheckoutService _checkoutService;
public CheckoutController(ICheckoutService checkoutService) =>
_checkoutService = checkoutService;
[HttpGet]
public virtual ActionResult Summary()
{
var shoppingCartData = _checkoutService.GetShoppingCart(Session["..."]);
// The viewmodel here could be returned by your service or the service
// would return all required data and the viewmodel simply transforms that Dto into what is needed by the UI
var summaryViewModel = new CheckoutSummaryViewModel()
{
Products = shoppingCartData
};
return View("_Summary", summaryViewModel);
}
}

Values from asp net form to Dto

Going from this article here what i am looking to do is to get the key value pairs sent by an aspnet/html form and then put them into a dto that i can then use elsewhere in my application. I see that inside the foreach loop
public async Task<HttpResponseMessage> PostFormData()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
await Request.Content.ReadAsMultipartAsync(provider);
// Show all the key-value pairs.
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
Trace.WriteLine(string.Format("{0}: {1}", key, val));
}
}
you can read the values and send them to traceline. From there how would you go about turning them into a dto?
to go along with the example in the link. i want to get
public class trip{
public string triptype {get; set;}
public string airports{get; set;}
DateTime? dates {get; set;}
}
I see you've found a way round it now, but a simpler approach would be as follows, using the default model binding functionality built into Web API.
public async Task<HttpResponseMessage> PostFormData(Trip tr)
{
//do whatever you want here, you've already got a Trip object fully-formed (assuming the data is valid - the first thing you do you should be to check that):
if (!ModelState.IsValid) {
//return an error to the client
return Request.CreateResponse(HttpStatusCode.BadRequest, ModelState);
}
//otherwise, carry on and do whatever processing you need
///...
//last thing to do, return a response, something like:
return Request.CreateResponse(HttpStatusCode.OK, "Your request has been processed");
}
For this to work, the only requirement is that the names of the properties of the "Trip" object match those being submitted from your form. Judging by the property names you've given in your answer, you'd just need to modify your Trip object very slightly:
public class Trip {
public string trip { get; set; }
public string options { get; set; }
public string seat { get; set; }
}
If you don't want to do that, then do the opposite: modify the "name" attributes of the HTML form you're submitting from, so that they match the Trip object's property names.
And that's it - no need to manually populate the object properties from the form data.
If anyone is interested in how to do this the way i found that worked for me was this. I dont know if this is the best way. I do know that since receiving values like this is not normally used commonly the answer was not clear.
var tr = new Trip
{
Triptype = provider.FormData.GetValues("trip").FirstOrDefault(),
Options = provider.FormData.GetValues("options").FirstOrDefault(),
Seat = provider.FormData.GetValues("seat").FirstOrDefault(),
};

Why is construction taking a lot of time?

I have classes that I use with EntityFramework:
public partial class BaseDocument
{
public BaseDocument()
{
DocumentLinks = new List<DocumentLink>();
}
public int Id {set;get;}
public virtual List<DocumentLink> DocumentLinks {set;get;}
}
public partial class Payment:BaseDocument
{
}
public partial class Bill:BaseDocument
{
}
public partial class DocumentLink
{
public int Id{set;get;}
public int StartDocId{set;get;}
public int EndDocId{set;get;}
public virtual BaseDocument StartDoc{set;get;}
public virtual BaseDocument EndDoc{set;get;}
}
Now I select document with Linq and want to iterate through list of his DocumentLinks.
var payment = dbContext.Payments.First(t=>t.Id = id);
foreach(var link in payment.DocumentLinks)
{
if (link is Payment)
{
//do something
}
else if (link is Bill)
{
//do something
}
}
And my code works very slowly at the line if (link is Payment). After this line everything works quickly.
What is wrong?
You mean it is slow in the line that is actually executing the database query? Hint - this is why it is slow.
var payment = dbContext.Payments.First(t=>t.Id = id);
I fail to see how the payment includes the DocumentLiks - which means they are lazy loaded. Which means this happens in the foreach. And there you go. Slow.
Include them in the initial query.
Not a direct answer to your question, but a suggestion that you shouldn't type-sniff like this. Polymorphism allows you to ignore the exact type of an object, use it.
Put whatever behavior you need into BaseDocument and remove the is Payment and is Bill:
var payment = dbContext.Payments[id];
foreach(var link in payment.DocumentLiks)
{
link.DoSomething();
}
This may be because of Lazy loading.
In your DBContext configuration specify:
this.Configuration.LazyLoadingEnabled = false;

How to deal with custom Properties in EF?

In my app, i have a edmx file with some partial classes representing my tables, and a context class wich i have the methods i need i.e GetMessages() and GetMessageById(long idMessage).
In that case, i use the GetMessages() method to fill a grid. Everything normal.
The Message entity class is something like this:
[Table("Message")]
public partial class Message
{
public long IdMessage{get;set;}
public long IdStatus{get;set;}
}
The problem is that i have another table that i have the StatusDescription that i need to get using the IdStatus.
I created another partial class with this property:
public partial class Message
{
private static readonly MessageRepository MessageRepository ;
static Message()
{
MessageRepository = new MessageRepository();
}
public string StatusDescription
{
get { return MessageRepository .GetMessageDescription(this.Cd_SchedulerStatus); }
}
}
And the method in the MessageRepository:
public MessageRepository()
{
_appContext= AppContext.GetContext();
}
public string GetMessageStatusDescription(int statusId)
{
var status = _appContext.Message.FirstOrDefault(id => id.IdStatus.Equals(statusId));
return status != null ? status.StatusDescription : string.Empty;
}
I know that it generates problems and it is not the best approach to deal with it, because im acessing the data inside the entity class, im having the n+1 problem, each time i send a new query to the database.
I would like to know if somebody have this problem and whats the best solution?
I suggest you create a new context for each message description request:
public string GetMessageStatusDescription(int statusId)
{
using (var appContext = AppContext.GetContext())
{
var status = appContext.Message.FirstOrDefault(id => id.IdStatus == statusId);
return status != null ? status.StatusDescription : string.Empty;
}
}

Comparing two models in .NET

Lets imaging the we have model:
public class InheritModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string OtherData { get; set; }
}
We have a controller with View, that represents this model:
private InheritModel GetAll()
{
return new InheritModel
{
Name = "name1",
Description = "decs 1",
OtherData = "other"
};
}
public ActionResult Index()
{
return View(GetAll());
}
Now we can edit this in View, change some data and post in back to server:
[HttpPost]
public ActionResult Index(InheritModel model)
{
var merged = new MergeModel();
return View(merged.Merge(model, GetAll()));
}
What i need to do:
In view we have a reproduction of model
User change something and post
Merge method need to compare field-by-field posted model and previous model
Merge method create a new InheritModel with data that was changed in posted model, all other data should be null
Can somebody help me to make this Merge method?
UPDATE(!)
It's not a trivial task. Approaching like:
public InheritModel Merge(InheritModel current, InheritModel orig)
{
var result = new InheritModel();
if (current.Id != orig.Id)
{
result.Id = current.Id;
}
}
Not applicable. It's should be Generic solution. We have more than 200 properties in the model. And the first model is built from severeal tables from DB.
public InheritModel Merge(InheritModel current, InheritModel orig)
{
var result = new InheritModel();
if (current.Id != orig.Id)
{
result.Id = current.Id;
}
if (current.Name != orig.Name)
{
result.Name = current.Name;
}
... for the other properties
return result;
}
Another possibility is to use reflection and loop through all properties and set their values:
public InheritModel Merge(InheritModel current, InheritModel orig)
{
var result = new InheritModel();
var properties = TypeDescriptor.GetProperties(typeof(InheritModel));
foreach (PropertyDescriptor property in properties)
{
var currentValue = property.GetValue(current);
if (currentValue != property.GetValue(orig))
{
property.SetValue(result, currentValue);
}
}
return result;
}
Obviously this works only for 1 level nesting of properties.
Per topic, it seems that what you want is a sort of "change tracking" mechanism which is definitely not trivial or simple by any means. Probably, it makes sense to use any modern ORM solution to do that for you, does it?
Because otherwise you need to develop something that maintains the "context" (the 1st level object cache) like EF's ObjectContext or NH's Session that would be generic solution.
Also, there is no information on what happens at the lower level - how do you actualy save the data. Do you already have some mechanism that saves the object by traversing it's "non-null" properties?
I have a similar project experience, which made me thought a lot about the original design. Think the following question:
You have a view that representing a model, then users modified
something of the model in the view, all the CHANGES are posted to
server and the model is modified, and then it's saved to database
probably. What's posted to the server on earth?
An instance of InheritModel? No. You want the changes only. It's actually part of InheritModel, it's a InheritModel Updater, it's an instance of Updater<InheritModel>. And in your question you need to merge two models, because your Update method looks like:
public InheritModel Update(InheritedModel newModel)
{
//assign the properties of the newModel to the old, and save it to db
//return the latest version of the InheritedModel
}
Now ask yourself: why do I need a whole instance of InheritedModel when I just want to update one property only?
So my final solution is: posting the changes to the controller, the argument is something like a Updater<TModel>, not TModel itself. And the Updater<TModel> can be applied to a TModel, the properties metioned in the updater is assigned and saved. There shouldn't a MERGE operation.

Categories

Resources