Writing new EF core entities does not use the auto_increment but writes 0 value as ID - entity-framework-core

I'm currently programming a modal to add some basic information to print an invoice with that information later on. The code is still messy but as soon as i figure out how to solve my problem, I'm going to smarten up the code a little bit.
I'm currently struggling in creating some input fields that are used to add or remove the items of the invoice. Currently it looks like that:
When I open that modal, I retrieve the OrderSpecifications (that's what I call these lines) from the DB and populate the input fields.
protected override void OnInitialized()
{
specs = nfzContext.OrderSpecifications.Where(x => x.FkOrderNumber == order.Id).ToList();
numberOfSpecLines = nfzContext.OrderSpecifications.Where(x => x.FkOrderNumber == order.Id).Count();
SetupSpeclines();
}
I have 5 input fields predefined, which are only hidden in case there are no specification lines already existing. If i press the + button, I show the a new line.
<div class="card-body">
<div class="form-group">
<div class="row">
<div class="col">
<input class="form-control" type="text" #bind="specification1.ItemName" hidden="#specLine1Disabled" placeholder="Zeile 1" />
</div>
</div>
<div class="row">
<div class="col">
<input class="form-control" type="text" #bind="specification2.ItemName" hidden="#specLine2Disabled" placeholder="Zeile 2" />
</div>
</div>
</div>
</div>
The SetupSpecline method grabs the existing speclines and adds a reference for each to one of the five specification1 ... specification5 variables:
void SetupSpeclines() {
if (numberOfSpecLines <= 1) {
specLine1Disabled = false;
if (numberOfSpecLines == 1) specification1 = specs.ElementAt(0);
numberOfVisibleSpecLines = 1;
}
else if (numberOfSpecLines == 2) {
specLine1Disabled = false;
specLine2Disabled = false;
specification1 = specs.ElementAt(0);
specification2 = specs.ElementAt(1);
numberOfVisibleSpecLines = 2;
}
else if (numberOfSpecLines == 3) {
specLine1Disabled = false;
specLine2Disabled = false;
specLine3Disabled = false;
specification1 = specs.ElementAt(0);
specification2 = specs.ElementAt(1);
specification3 = specs.ElementAt(2);
numberOfVisibleSpecLines = 3;
}
else if (numberOfSpecLines == 4) {
specLine1Disabled = false;
specLine2Disabled = false;
specLine3Disabled = false;
specLine4Disabled = false;
specification1 = specs.ElementAt(0);
specification2 = specs.ElementAt(1);
specification3 = specs.ElementAt(2);
specification4 = specs.ElementAt(3);
numberOfVisibleSpecLines = 4;
}
else if (numberOfSpecLines == 5) {
specLine1Disabled = false;
specLine2Disabled = false;
specLine3Disabled = false;
specLine4Disabled = false;
specLine5Disabled = false;
specification1 = specs.ElementAt(0);
specification2 = specs.ElementAt(1);
specification3 = specs.ElementAt(2);
specification4 = specs.ElementAt(3);
specification5 = specs.ElementAt(4);
numberOfVisibleSpecLines = 5;
}
}
This it the database model for OrderSpecification (ID = primary key):
namespace MyNamespace
{
public class OrderSpecification
{
public OrderSpecification();
public int Id { get; set; }
public int FkOrderNumber { get; set; }
public int SeqId { get; set; }
public string ItemName { get; set; }
public virtual Order FkOrderNumberNavigation { get; set; }
}
}
You can unhide (+) up to five inputs and enter some data. After you press the OK button, the routine starts to check if individual lines have a) altered (=ItemName changed), if new ones were added or if some were removed (=empty input):
void Confirm()
{
List<OrderSpecification> linesToAdd = new List<OrderSpecification>();
List<OrderSpecification> linesToRemove = new List<OrderSpecification>();
if (!string.IsNullOrEmpty(specification1.ItemName))
{
// Check if there is a spec at index 0
if (specs.ElementAtOrDefault(0) != null)
{
specs.ElementAtOrDefault(0).ItemName = specification1.ItemName; // Only itemName has changed
}
else
{ // Add new line
linesToAdd.Add(new OrderSpecification { FkOrderNumber = order.Id, ItemName = specification1.ItemName, SeqId = 1 });
}
}
else if (!string.IsNullOrEmpty(specification1.ItemName) && specs.ElementAtOrDefault(0) != null)
Now, while all that works just fine, I have trouble writing the new speclines to the database. For example, When i run
foreach (var spec in LinesToAdd)
{
nfzContext.Add(spec);
}
nfzContext.SaveChanges();
I get the error message
{"Cannot insert explicit value for identity column in table
'OrderSpecifications' when IDENTITY_INSERT is set to OFF."}
What I assume is that EF Core tries to add the new OrderSpecification with the ID=0, which is the standard value when creating a new OrderSpecification element. I need to tell EF Core to not write the ID as 0 but to let the database set the value by using auto_increment.
And what's odd is, although I have assigned the Primary Key to the ID field, when I scaffold, the key is not set in the modelbuilder:
modelBuilder.Entity<OrderSpecification>(entity =>
{
entity.ToTable("OrderSpecifications", "samnfz");
entity.Property(e => e.Id).HasColumnName("ID");
entity.Property(e => e.FkOrderNumber).HasColumnName("FK_OrderNumber");
entity.Property(e => e.ItemName).IsRequired();
entity.Property(e => e.SeqId).HasColumnName("SeqID");
entity.HasOne(d => d.FkOrderNumberNavigation)
.WithMany(p => p.OrderSpecifications)
.HasForeignKey(d => d.FkOrderNumber)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_OrderSpecifications_Orders");
});
Any idea?

Ugh, I think I have found the error. After analyzing the table structure in the modelbuilder, I recognized that the structure is not the same that I have in my database. So i scaffolded once again and the error is gone. obviously, I used model types that were not current and maybe the primary key was set to another attribute...

Related

Blazor drag and drop how to get target object?

I can't seem to figure out the right way to get the target object. Here is the code front end code that is supposed to have drag and drop functionality:
<div class="pos-top">
<div id="imgGrid" class="grid bg-white" style="grid-template-columns:repeat(#columnCount, #(unitWidth)); grid-auto-flow:dense;">
#foreach (var b in blocks)
{
#if ((b.Placement[_pageType].Visible == true || showHiddenBlocks == true) && b.Zones != null && b.Zones.Contains(zone))
{
var id = b.Id;
<div class="col-span-#b.ColSpan row-span-#b.RowSpan relative border border-black box-border #(b.isDragOver?"dropped":"")" style=" order:#b.Placement[_pageType].Order;" #ondblclick="(() => ChangeBlockProperties(b))"
draggable="true"
data-block-id="#b.Id"
id="#id" #ondrop="#((e) => ondropOver(b, blocks.ToList()))"
ondragover="event.preventDefault();"
#ondragstart="#((e) => ondragstart(e, b, blocks.ToList()))"
#ondragenter="#(() => ondragenter(b))"
#ondragleave="#(() => { b.isDragOver = false; })"
#ondragend="#(() => ondragend(b, blocks.ToList()))">
<div class="blockNumberInfo absolute rounded-full bg-red-700 flex justify-center items-center border-2 border-black"
style="width:40px;height:20px">
#b.LocalIndex / #b.Placement[_pageType].Order
</div>
</div>
}
}
</div>
}
}
</div>
This is my code that is moving the blocks around:
public async void ondropOver(FlyerBlock item, List<FlyerBlock> flyerBlocks)
{
DragEnter = null;
if (DraggedItem == null) return;
if (DraggedItem == item) return;
DraggedItem.Placement[_pageType].Order = item.Placement[_pageType].Order;
await BlockplacementEditService.SaveBlockChangesAsync(flyerBlocks, DraggedItem, DraggedItem.Placement[_pageType].Order, _pageType, zone);
DraggedItem = null;
item.isDragOver = false;
//StateHasChanged();
}
public void ondragstart(DragEventArgs e, FlyerBlock item, List<FlyerBlock> flyerBlocks)
{
e.DataTransfer.EffectAllowed = "move";
DraggedItem = item;
DraggedItemPosition = item.Placement[_pageType].Order;
}
public void ondragenter(FlyerBlock item)
{
item.isDragOver = true;
DragEnter = item;
}
public async void ondragend(FlyerBlock item, List<FlyerBlock> flyerBlocks)
{
item.isDragOver = false;
if (DraggedItem == null) return;
DragEnter = null;
// item.isDragOver = true;
}
The issue I am running into is that I dont know how to pass the targetblock into my drop over event. I tried using DragEventArgs but that does not work I have also tried using jsruntime but I can only extract the dragged block. I want to be able to get the target block so I can update the order correctly. Any help would be appreciated!

Html.DropDownListFor default selected value does not work

I have read hundreds of posts about this problem and I still can't find a solution.
Please help with this horrible mistery;
I would like to have different default values in my DropDownListFor. The "PartialViewList1 exists out of 4 items.
I want the DropDownListFor to select the id of the current item. (item.id)
But because of testing purposes I just filled in "3". And even that doesn't work.
The Models are filled correctly, I am able to add more code of the controller but that wouldn't add much. But please ask if you want me to.
And yes I know that it is better to make the SelectList in the controller, but first I want to make it work.
View:
#foreach (var item in Model.PartialViewList1)
{
<tr>
<td>Plaats: </td>
<td>#item.PlaceNumber</td>
<td>
#Html.DropDownListFor(x => x.PartialView.Id, new SelectList(Model.PartialViewList2, "Id", "Name", 3),
new { onchange = "this.form.submit();" })</td>
</tr>
}
Screen shot of the users view
I hope that maybe someone can use this for his or her problem.
With Stephen Mueke I have found the solution. The problem is that if "x => x.PartialView.Id" already has a value then the default value : "3" will be overriden by the Id.
And you can't generate multiple DropDownlistFor's while binding them to the same property.
My solution on my problem:
View:
#using (Html.BeginForm("_PartialSettingsDropDownList1", "Home")){
<table>
#for (int i = 0; i < Model.maxNumberOfViews; i++)
{
<tr>
<td>
Plaats #(i+1)
</td>
<td>
#Html.DropDownListFor(x => Model.PartialViewList[i].ID, new SelectList(Model.PartialViewList, "Id", "Name", Model.PartialViewList[i].ID), "select")
</td>
</tr>
}
</table>
#Html.HiddenFor(x => x.maxNumberOfViews)
<input class="submit" type="submit" value="Submit" />}
Controller:
[HttpGet]
public PartialViewResult _PartialSettingsDropDownList1()
{
PartialScreenViewModel viewModel = new PartialScreenViewModel();
viewModel.PartialViewList = homeModel.AllBoxViews(databaseRepository.PartialViews);
viewModel.maxNumberOfViews = viewModel.PartialViewList.Count();
return PartialView(viewModel);
}
[HttpPost]
public RedirectResult _PartialSettingsDropDownList1(PartialScreenViewModel viewModel)
{
for (int i = 0; i < viewModel.maxNumberOfViews; i++)
{
PartialView viewOnScreen = databaseRepository.PartialViews.FirstOrDefault(x => x.ID == viewModel.PartialViewList[i].ID);
databaseRepository.UpdatePartialView(viewOnScreen, i+1);
}
return new RedirectResult("Settings");
}
Model:
public List<PartialView> AllBoxViews(IEnumerable<PartialView> allViews)
{
List<PartialView> OnlyBoxViews = new List<PartialView>();
foreach (var item in allViews.Where(item => item.Type.Equals("box")))
{
OnlyBoxViews.Add(item);
}
return OnlyBoxViews;
}
ViewModel:
public class PartialScreenViewModel
{
public List<PartialView> PartialViewList { get; set; }
public int maxNumberOfViews { get; set; }
}
Result on screen: screenshot

ZK Reordering With Listbox Without Drag And Drop Event

As i am trying This example well define by Nabil Abdel-Hafeez
It is working fine with some small issue which i already mentioned in tracker as issue. But i will want to Open a DualBox modal window in which one listbox contain all header name and other listbox will contain which header we will want to show for a listbox(I did this with getitemrendered ).I will want to use same ZUL Code without getitemrendered method.But user can hide the header which he/she do not want to see for a listbox. Anyone did this type of things?
Here
The green image with + Sign showing same thing which i will want to implement.
As I was trying the Nabil Abdel-Hafeez but my issue is that i will provide duallistbox where user can select which header he/she will want to see in listbox, user can select header by clicking on button ,user can add one header or all header from duallistbox and when user click on the Reorder button of duallistbox then it will reorder .In Nabil demo he is doing something like this..
for (Listitem item : lHead.getListbox().getItems()) {
item.insertBefore(item.getChildren().get(from), item.getChildren().get(to));
}
But if user selecting multiple how we will track which will come first which second and so on..
You can try combine MVVM with forEach so you can construct String array to display, this works since 6.0.2
e.g.,
zul
<zk>
<div apply="org.zkoss.bind.BindComposer"
viewModel="#id('vm') #init('test.TestVM')">
<listbox model="#load(vm.model)">
<listhead>
<listheader forEach="${vm.headers}" label="${each}" />
</listhead>
<template name="model" var="cells">
<listitem>
<listcell forEach="${cells}" label="${each}" />
</listitem>
</template>
</listbox>
<button label="original seq" onClick="#command('originalSeq')" />
<button label="reverse" onClick="#command('reverse')" />
</div>
</zk>
VM
package test;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;
import java.util.*;
public class TestVM {
private int[] _original = {1, 2, 3};
private int[] _reverse = {3, 2, 1};
private int[] _seq = _original;
private List _rawData;
public String[] getHeaders () {
String[] headers = new String[_seq.length];
for (int i = 0; i < _seq.length; i++) {
int idx = _seq[i];
headers[i] = (idx == 1? "First Name" :
idx == 2? "Last Name" :
idx == 3? "Age" : "");
}
return headers;
}
public ListModel getModel () {
if (_rawData == null) {
getRawData();
}
List modelData = new ArrayList();
for (int i = 0; i < _rawData.size(); i++) {
Person data = (Person)_rawData.get(i);
String[] cells = new String[_seq.length];
for (int j = 0; j < _seq.length; j++) {
cells[j] = data.getValue(_seq[j]);
}
modelData.add(cells);
}
return new ListModelList(modelData);
}
public void getRawData () {
_rawData = new ArrayList();
_rawData.add(new Person("First Name 01", "Last Name 01", 21));
_rawData.add(new Person("First Name 02", "Last Name 02", 22));
_rawData.add(new Person("First Name 03", "Last Name 03", 23));
}
#Command
#NotifyChange("model")
public void originalSeq () {
_seq = _original;
}
#Command
#NotifyChange("model")
public void reverse () {
_seq = _reverse;
}
class Person {
private String _firstName;
private String _lastName;
private int _age;
public Person (String firstName, String lastName, int age) {
_firstName = firstName;
_lastName = lastName;
_age = age;
}
public String getFirstName () {
return _firstName;
}
public String getLastName () {
return _lastName;
}
public int getAge () {
return _age;
}
public String getValue (int i) {
return i == 1? getFirstName() :
i == 2? getLastName() :
i == 3? getAge() + "" : "";
}
}
}
Regarding forEach, please refer to ZK Iterative Evaluation
Edit
Fully binded sample at ZK fiddle
Listbox Reorder Cells

Customise Validation summary

I have used html.ValidationSummary to get all errors displayed on top of the page.
This will render list with errors on top of the page.
Example:
<ul>
<li>UserName is invalid</li>
</ul>
I have how ever need to render every item instead of list as custom div with additional html tags inside.
I need every line to be rendered as short example below (this is only one line):
<div>
<div class="right"><a href="#closeError">Close error</div>
<div class="right"><a href="#Update">Update Field</div>
<label>Error:</label> Name on the page is invalid.
</div>
What is your opininon how to achieve this rendering?
I have considered to create html helper where i will take ModelState and get all errors, but not sure this will work...
I have considered to create html helper where i will take ModelState and get all errors, but not sure this will work...
Why wouldn't that work?
public static class ValidationExtensions
{
public static IHtmlString MyValidationSummary(this HtmlHelper htmlHelper)
{
var formContext = htmlHelper.ViewContext.ClientValidationEnabled
? htmlHelper.ViewContext.FormContext
: null;
if (formContext == null && htmlHelper.ViewData.ModelState.IsValid)
{
return null;
}
var sb = new StringBuilder();
var htmlSummary = new TagBuilder("div");
var modelStates = htmlHelper.ViewData.ModelState.Values;
sb.AppendLine("<div class=\"right\"><a href=\"#closeError\">Close error</div>");
sb.AppendLine("<div class=\"right\"><a href=\"#Update\">Update Field</div>");
if (modelStates != null)
{
foreach (ModelState modelState in modelStates)
{
foreach (ModelError modelError in modelState.Errors)
{
var userErrorMessageOrDefault = GetUserErrorMessageOrDefault(modelError);
if (!string.IsNullOrEmpty(userErrorMessageOrDefault))
{
sb.AppendFormat("<label>Error:</label> {0}{1}", htmlHelper.Encode(userErrorMessageOrDefault), Environment.NewLine);
}
}
}
}
htmlSummary.InnerHtml = sb.ToString();
if (formContext != null)
{
formContext.ReplaceValidationSummary = true;
}
return MvcHtmlString.Create(htmlSummary.ToString(TagRenderMode.Normal));
}
private static string GetUserErrorMessageOrDefault(ModelError error)
{
if (!string.IsNullOrEmpty(error.ErrorMessage))
{
return error.ErrorMessage;
}
return null;
}
}
and then:
<%= Html.MyValidationSummary() %>

SelectList Object selectedValue issue

I'm having troubles with the selectedValue option for SelectedItems, for some reason it won't select the item despite it being in the list...
My Controller:
public ActionResult CreateTransformer(string edit)
{
var equipment = GenIDQueries.FindEquipment(edit);
ViewData["Feeder"] = new SelectList(GenIDQueries.GetFeeders(equipment.OpsCentre.ToString()),
"CircuitID",
"CircuitDescription",
equipment.Feeder);
return View(equipment);
}
equipment.Feeder is of type Integer.
My View:
<p>
<b><%=Html.LabelFor(m=>m.Feeder) %>:</b><font color="red">*</font>
<%=Html.DropDownListFor(m=>m.Feeder, ViewData["Feeder"] as SelectList, "") %>
<%= Html.ValidationMessageFor(m => m.Feeder)%>
</p>
My GenIDQueries.GetFeeders:
public static IEnumerable<Circuit> GetFeeders(string distNo)
{
int distNoNumber;
if ( int.TryParse(distNo, out distNoNumber))
{
return ActiveRecordLinq.AsQueryable<Circuit>()
.Where(x => x.DistrictCircuitRelations
.Any(y => y.District.DistrictNo == distNoNumber))
.OrderBy(x => x.CircuitDescription)
.Select(x => new Circuit
{
CircuitID = x.CircuitID,
CircuitDescription = x.CircuitDescription
});
}
return new List<Circuit>();
}
I have verified that the element I wanted to select is indeed returned by GenIDQueries, however when the page loads it never selects that option, in the HTML source code, the item is not selected either.
Thanks for the help!
When setting the selected value you should set it to the selected CircuitID and not the Feeder object.
Why are you using this Plague of ViewData? I consider ViewData as a virus started at Microsoft open space laboratories and spread through internet blog posts and articles.
View models are the way to go in ASP.NET MVC:
Model:
public class MyViewModel
{
public string SelectedValue { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
}
Controller:
public ActionResult CreateTransformer(string edit)
{
var equipment = GenIDQueries.FindEquipment(edit);
var items = GenIDQueries.GetFeeders(equipment.OpsCentre.ToString());
var model = new MyViewModel
{
SelectedValue = equipement.CircuitID,
Items = new SelectList(items, "CircuitID", "CircuitDescription")
};
return View(model);
}
View:
<%= Html.DropDownListFor(m => m.CircuitID, Model.Items, "") %>
<%= Html.ValidationMessageFor(m => m.CircuitID) %>