I searched for the answer on the website but I did not find one. I have the following problem ...
I'm trying to update multiple records in the database as follows:
public void SaveJItem(List<DataForDespatcher> Jitem)
{
JitemsTable.InsertAllOnSubmit(Jitem.Where(i => i.Id ==0));
JitemsTable.AttachAll(Jitem.Where(i => i.Id != 0));
JitemsTable.Context.Refresh(RefreshMode.KeepCurrentValues, Jitem);
JitemsTable.Context.SubmitChanges();
}
The table is described as follows:
[Table(Name = "tanks")]
public class DataForDespatcher
{
[Column(IsPrimaryKey = true, IsDbGenerated = true,AutoSync = AutoSync.OnInsert)]
public int Id { get; set; }
/*bla bla bla */
}
When I update I get the error:
"DuplicateKeyException" in "JitemsTable.AttachAll(Jitem.Where(i => i.Id != 0));".
How do I correctly update the data?
ADD:
razor update form:
#inherits WebViewPage<IEnumerable<DomainModel.Entities.DataForDespatcher>>
/*bla bla bla*/
data controller save(get):
public ViewResult EditForDispatcher(int group)
{
var list = DataRep.JItems.Where(x => x.group == group).Select(x => x);
return View(list);
}
data controller save(post):
[HttpPost]
public ActionResult EditForDispatcher(List<DataForDespatcher> Jitem, string addNewOperation, string sendParam, string operations)
{
if (ModelState.IsValid)
{
int group = DataRep.JItems.ToList().Max(x => x.group + 1);
if (Jitem.Any(x => x.group != 0))
foreach (var dataForDespatcher in Jitem)
dataForDespatcher.group = Jitem.Where(x=>x.group!=0).Select(x=>x.group).First();
else
foreach (var dataForDespatcher in Jitem)
dataForDespatcher.group = group;
DataRep.SaveJItem(Jitem);
}
return View(Jitem);
}
I mean exception is occur because you have both an updated and new items in List and the first in the list is not inserted item. I think, you must do somethong like this:
JitemsTable.InsertAllOnSubmit(Jitem.Where(i => i.Id ==0));
JitemsTable.AttachAll(Jitem.Where(i => i.Id != 0));
JitemsTable.Context.Refresh(RefreshMode.KeepCurrentValues, Jitem);
JitemsTable.Context.SubmitChanges();
Related
I have a razor view in ASP.NET MVC looping over an array of objects from my model and generating corresponding html controls.
My html elements are properly bound, except my drop down lists who can't seem to select the value provided to them by the model.
My view: (in the hereby case, I'm simply displaying a list of countries)
#for (var i = 0; i < Model.answers.Count(); i++)
{
<div class="form-group">
...
#switch (Model.answers[i].Statement.QuestionType)
{
...
case ExternalEnums.QuestionTypeEnum.country:
#Html.DropDownListFor(Model => Model.answers[i].Value,
new SelectList(Model.Pays, "Value", "Text"))
break;
}
...
</div>
}
My view controller, generating the country list items and retrieving the existing model entries:
public class HomeIndexViewModel
{
private QuestionsModelContainer dbContext;
private AdmcommonEntities admCommonContext;
...
public List<Answer> answers { get; private set; }
private IEnumerable<SelectListItem> _countries;
public IEnumerable<SelectListItem> Pays
{
get
{
if (_countries == null)
SetCountries();
return _countries;
}
}
public HomeIndexViewModel()
{
Init(-1, null);
}
public HomeIndexViewModel(int page, string _pageWideError = null)
{
Init(page, _pageWideError);
}
private void Init(int page, string _pageWideError = null)
{
dbContext = new QuestionsModelContainer();
PageNum = page;
pageWideError = _pageWideError;
answers = GetAnswers();
...
}
private void SetCountries()
{
using (admCommonContext = new AdmcommonEntities())
{
var localEntities = admCommonContext.Pays.ToList();
var localList = new List<SelectListItem>();
localList.Add(new SelectListItem());
foreach (var item in localEntities)
{
var newItemList = new SelectListItem();
newItemList.Text = item.Libelle;
newItemList.Value = item.Libelle;
localList.Add(newItemList);
}
_countries = localList;
}
}
public List<Statement> GetStatements()
{
var statements = dbContext.StatementSet.Where(w => w.Page == PageNum).OrderBy(w => w.Order).ToList();
return statements;
}
public List<Answer> GetAnswers()
{
var statements = GetStatements();
var ExistingAnswers = new List<Answer>();
if (AdminPermissionManager.IsUserAuthenticated()) //Loading existing entries.
ExistingAnswers = Answer.GetExistingAnswers(statements, dbContext);
var answers = new List<Answer>();
foreach (var item in statements)
{
var answer = ExistingAnswers.Where(w => w.StatementId == item.Id).FirstOrDefault();
if (answer == null)
{
answer = new Answer();
answer.StatementId = item.Id;
answer.Statement = item;
}
answers.Add(answer);
}
return answers;
}
}
My model class, simply containing the value I'm trying to display:
[MetadataType(typeof(AnswerMetaData))]
public partial class Answer
{
...
public static List<Answer> GetExistingAnswers(List<int> statementIds, QuestionsModelContainer dbContext)
{
List<Answer> ExistingAnswers;
var usercode = AdminPermissionManager.GetUserCode();
ExistingAnswers = dbContext.AnswerSet.Where(w => statementIds.Contains(w.StatementId) && w.ChildCode == usercode).ToList();
return ExistingAnswers;
}
public static List<Answer> GetExistingAnswers(List<Statement> statements, QuestionsModelContainer dbContext)
{
var statementIds = statements.Select(w => w.Id).ToList();
return GetExistingAnswers(statementIds, dbContext);
}
}
public class AnswerMetaData
{
[InternalValidation]
public string Value { get; set; }
private class InternalValidationAttribute : ValidationAttribute
{
...
}
}
I'm sure there's something very obvious that I'm missing, but can't figure out what exactly :/...
You're nearly there actually, this part in the View:
#Html.DropDownListFor(
Model => Model.answers[i].Value,
new SelectList(Model.Pays, "Value", "Text")
)
You create a new selectlist - each time, but you already have a IEnumerable<SelectListItem> created, so you don't have to recreate that list. The only thing you might be missing (most likely) is the "Selected" item option.
If you already have a value selected (and it isn't the first one) it will not be selected dropdown option - also because you pass the value of the selected option as the "ID" of the field (not the actual value) - DropDownListFor is kinda weird in that regard.
So you want to change your #Html.DropDownListFor to something like this:
#Html.DropDownListFor(
Model => Model.answers[i].Name,
Pays(Model.answers[i].Value)
)
When that being done you should change your property "Pays" in the ViewModel to a method that accepts a value (idk what you're using, but let's assume it's string) - to something along the lines of this:
public IEnumerable<SelectListItem> Pays(string selectedValue)
{
if (_countries == null) SetCountries();
var value = new List<SelectListItem>();
foreach(var item in _countries)
{
item.Selected = (item.Value == selectedValue);
value.Add(item);
}
return value;
}
This above is a bit pseudocoded since I'm typing this from memory, but it should get you into the correct direction. Also remember to check with the inspect element in the browser if the dropdown HTML element really has the correct name attribute.
I have a method where list cannot convert to ienumerable. How do i cast???
public ActionResult Attending()
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier).Value;
var gigs = _context.Attendances.Include(a => a.Gig.Artist).Include(a => a.Gig.Genre).Where(a => a.AttendeeId == userId).ToList();
var viewModel = new GigsViewModel()
{
UpcomingGigs = gigs,
ShowActions = User.Identity.IsAuthenticated,
Heading = "Gigs I'm Attending"
};
return View("Gigs", viewModel);
}
Here is my ViewModel:
public class GigsViewModel
{
public IEnumerable<Gig> UpcomingGigs { get; set; }
public bool ShowActions { get; set; }
public string Heading { get; set; }
}
Try using below code, AsEnumerable() will do your work
var gigs = _context.Attendances.Where(a => a.AttendeeId == userId).select(a=>
new Gig()
{
property = a.property //assuming property, you can repeat the same for other properties of Gig
}).AsEnumerable();
The result of a Linq database query is typically IQueryable which is derived from IEnumerable, IQueryable, and IEnumerable.
In your case,it's linq database query so you need to call AsEnumerable();
You can also first fetch all attendees, and select the gigs.
IEnumerable<Gig> gigs = _context.Attendances.Where(a => a.AttendeeId == userId).Select(a => a.Gig).ToList();
Be aware if there can be multiple similar gigs, then perhaps you need only distinct set of gigs using Distinct:
IEnumerable<Gig> gigs = _context.Attendances.Where(a => a.AttendeeId == userId).Select(a => a.Gig).Distinct().ToList();
See more at: https://msdn.microsoft.com/en-us/library/bb534803(v=vs.110).aspx
Edited: edited the old suggestion, Distinct and Select added.
I have three tables
News
NewsCategory
Category
When I create a new News item, I need to assign categories to that new item.
My code looks like that
var NewsToSave = new News();
NewsToSave.NewsBody = model.NewsBody;
NewsToSave.NewsTitle = model.NewsTitle;
NewsToSave.NewsImagePath = NewsImagePath;
NewsToSave.NewsDate = System.DateTime.Now;
db.News.Add(NewsToSave);
db.SaveChanges();
foreach (var id in SelectedIDs)
{
// How to assign selected categories to NewsToSave object and save the Ids in the middle table
}
How to assign selected categories to NewsToSave object?
Thank you
You could override your context this way:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<NewsToSave>()
.HasMany(c => c.Categories).WithMany(i => i.NewsToSaves)
.Map(t => t.MapLeftKey("NewsToSaveID")
.MapRightKey("CategoryID")
.ToTable("NewsCategory"));
}
And process the added data:
void AddOrUpdateNews(Context context, int categoryId, string newsTitle)
{
var cat = context.Categories.SingleOrDefault(c => c.Id == categoryId);
var nws = cat.News.SingleOrDefault(n => n.Title == newsTitle);
if(nws == null)
{
cat.News.Add(context.News.SingleOrDefault(c => c.Title == newsTitle));
}
}
This worked great on the ASP.NET application I made a few months ago. Hope it can help you out.
You can create a category for each id, attach it (provided that it exists in the db already) and then add it to the Categories list of the news and save:
foreach(var id in SelectedIDs)
{
var category = new Category { CategoryId == id};
db.Categories.Attach(category);
NewsToSave.Add(category);
}
db.News.Add(NewsToSave);
db.SaveChanges();
foreach (var id in SelectedIDs)
{
// You have to load the category from Db
var cat = db.Categories.FirstOrDefault(x=> c.Id == id);
// Added to the NewsToSave
if (cat !=null)
NewsToSave.Categories.Add(cat);
}
// Store the changes
db.SaveChanges();
In my current MVC Project, I have a controller with the following method:
public ActionResult Index(string answer)
{
using (S3WEntities1 ent = new S3WEntities1())
{
afqList.Question = ent.Questions.Where(w => w.QuQuestionId == 1).Select(s => s.QuQuestion).FirstOrDefault().ToString();
afqList.Answers = ent.Answers.Where(w => w.AnsQuestionId == 1).Select(s => s.AnsAnswer).ToList();
}
return View(afqList);
}
However, this method is repeated 5 times, all with the only difference being that the number in (w => w.QuQuestionId == x) and (w => w.AnsQuestionId == x) changes, as well as having 5 different, although still similar, views for each method. How would I make this code a lot better than having 5 almost identical methods, but all still having different views? Thanks in advance!
EDIT:
I should also mention that in each of these methods, the corresponding view has a
#using (Html.BeginForm("Question3", "ControllerName", "FormMethod.Post))
and so need to call different methods based on which one comes next and is stated in the views.
Replace the number with x which will be passed as parameter
public ActionResult Index(string answer, int x)
{
using (S3WEntities1 ent = new S3WEntities1())
{
afqList.Question = ent.Questions.Where(w => w.QuQuestionId == x).Select(s => s.QuQuestion).FirstOrDefault().ToString();
afqList.Answers = ent.Answers.Where(w => w.AnsQuestionId == x).Select(s => s.AnsAnswer).ToList();
}
return View(afqList);
}
First add to your model:
public string NextQuestion { get; set; }
Then you can use it in your action and view:
public ActionResult Index(string answer, int questionId)
{
using (S3WEntities1 ent = new S3WEntities1())
{
afqList.Question = ent.Questions.Where(w => w.QuQuestionId == questionId).Select(s => s.QuQuestion).FirstOrDefault().ToString();
afqList.Answers = ent.Answers.Where(w => w.AnsQuestionId == questionId).Select(s => s.AnsAnswer).ToList();
}
afqList.NextQuestion = string.Format("Question{0}", questionId + 1);
return View(afqList);
}
Now in the View:
#using (Html.BeginForm(afqList.NextQuestion, "ControllerName", "FormMethod.Post))
I have got a task to delete the hierarchy of folders. When i am deleting a folder, the respective sub folders should be deleted.
public ActionResult DeleteLabel(int id)
{
var query = dbPanAgroDMSContext.LabelMaster.Where(x => x.ParentLabelId == id).ToList();
foreach(var item in query)
{
var query1 = dbPanAgroDMSContext.LabelMaster.Where(x => x.ParentLabelId == item.LabelId).ToList();
dbPanAgroDMSContext.LabelMaster.Remove(item);
foreach (var i in query1)
{
dbPanAgroDMSContext.LabelMaster.Remove(i);
}
}
LabelMaster label = dbPanAgroDMSContext.LabelMaster.Find(id);
dbPanAgroDMSContext.LabelMaster.Remove(label);
dbPanAgroDMSContext.SaveChanges();
return Json(new { Result = "OK" });
}
Instead of using repeated for loops I want to do it in a single block of code.Please help me to create a linq query?
Try this
public ActionResult DeleteLabel(int id)
{
Delete(id);
dbPanAgroDMSContext.SaveChanges();
return Json(new { Result = "OK" });
}
private void Delete(int id)
{
//For given id get all child ones first
var query = dbPanAgroDMSContext.LabelMaster.Where(x => x.ParentLabelId == id).ToList();
foreach(var item in query)
{
//for each child ,delet its' childs by calling recursively
Delete(item.Id);
}
LabelMaster label = dbPanAgroDMSContext.LabelMaster.Find(id);
dbPanAgroDMSContext.LabelMaster.Remove(label);
}