Asp.Net MVC Master Detail view using kendo grid - asp.net-mvc-5

I want to create contacts view. My model is:
public class Contact
{
public Contact()
{
Documents = new HashSet<Document>();
}
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string ContactNo { get; set; }
public string EmailId { get; set; }
public string Address { get; set; }
public string Notes { get; set; }
public ICollection<Document> Documents { get; set; }
}
public class Document
{
public Document() { }
public int Id { get; set; }
public int ContactId { get; set; }
public string DocumentNo { get; set; }
public string DocumentType { get; set; }
public byte[] FileContent { get; set; }
public string FileName { get; set; }
public int ContentLength { get; set; }
}
I have created view with Contact details and Grid for documents. Actually I am new to MVC so I am searched internet how to achieve this. But I cannot find any workable solution yet. I do not know how to add one or more document and persist document details in grid. What I am trying to achieve is save contact information with uploaded documents (one or more) while submit the form.

You can use the below code to achieve what you desire, using a parent child combination.
The below code is just a sample providing a view only option to detail view.
#model Models.Contact
<div id="ModelView">
<div >#Html.Label("Name")</div>
<div >
#Html.TextBoxFor(model => model.FirstName)
#Html.TextBoxFor(model => model.LastName)
</div>
...
...
<div id="grid"></div>
</div>
<script>
$(document).ready(function() {
$("#grid").kendoGrid({
dataSource: {
data: model.Documents,
schema: {
model: {
fields: {
//append fiels as per your document model
FileName: { type: "string" },
DocumentType: { type: "number" }
}
}
},
pageSize: 20
},
dataBound: OnDataBound
height: 550,
scrollable: true,
sortable: true,
columns: [
"FileName",
{ field: "FileName", title: "File Name", width: "130px", clientTemplate: "<input type='file' name='docs'/>" },
{ field: "DocumentType", title: "Document Type", width: "130px" }
]
});
});
function OnDataBound(e){
$('[name=docs]').kendoUpload(
{
async:
{
saveUrl: ......
removeUrl: ........
autoUpload: true
},
upload: onUpload, //Your custom function for uploader
success: onSuccess //Write the below function to display approprate message
});
}
</script>
Note: Above code will upload documents one by One rather than all documents at once, just for load balancing.

Related

Blazor creating a generic drop-down

I'm trying to create a generic dropdown component for use across our system. However, I'm encountering issues when binding the EventCallback for when the selected item is changed.
This is my current musings for the generic drop down:
<div class="inputItem #(SizeClass) dropdown" style="min-width:#(Width);">
<SfDropDownList TItem="object" TValue="int" Placeholder="Select a category" DataSource="DataSource" Value="#(SelectedItem)" EnableVirtualization="true">
<DropDownListEvents TItem="object" TValue="int" ValueChange="#OnSelectedItemChanged"></DropDownListEvents>
<DropDownListFieldSettings Text="#(TextField)" Value="#(ValueField)" />
</SfDropDownList>
</div>
#code {
[Parameter]
public IEnumerable<object> DataSource { get; set; }
[Parameter]
public EventCallback<ChangeEventArgs<int, object>> OnSelectedItemChanged { get; set; }
[Parameter]
public string Placeholder { get; set; }
[Parameter]
public string TextField { get; set; }
[Parameter]
public int SelectedItem { get; set; }
[Parameter]
public string ValueField { get; set; }
[Parameter]
public string Width { get; set; }
[Parameter]
public string SizeClass { get; set; }
}
And here's one example component that would call it:
#page "/news/create"
#inject NavigationManager NavManager;
#using Microsoft.EntityFrameworkCore;
#inject IDbContextFactory<FIS2_DbContext> contextFactory;
#inject IFileService fileService;
#using FIS2withSyncfusion.Controls;
#using FIS2withSyncfusion.Models;
#using FIS2withSyncfusion.Utility;
#using Syncfusion.Blazor.RichTextEditor;
#using System.Collections.Generic;
#using System.Threading.Tasks;
#using Newtonsoft.Json;
<div class="dashWrapper">
<SfDashboardLayout AllowDragging="false" AllowFloating="false" AllowResizing="false" CellAspectRatio="2.5" CellSpacing="#(new double[]{20,20})" Columns="3">
<DashboardLayoutPanels>
<DashboardLayoutPanel Column="0" Row="0" SizeX="2" SizeY="2" Id="createNews">
<HeaderTemplate>
<h3>Create A News Item</h3>
</HeaderTemplate>
<ContentTemplate>
<div class="form-wrapper">
<div class="inputRow">
<TextBox AutoComplete="#(Syncfusion.Blazor.Inputs.AutoComplete.Off)" Placeholder="Title" Text="#(title)" HTMLAttributes="#textboxValidation" Width="450px" SizeClass="half-width"></TextBox>
<DropDownList DataSource="categories" Placeholder="Select a category" SizeClass="half-width" Width="450px" TextField="name" ValueField="id" SelectedItem="#(itemModel.Category)" OnSelectedItemChanged="#(OnSelectedItemChanged)"></DropDownList>
#*<SfDropDownList TItem="spGetNewsCategoriesResult" TValue="int" Placeholder="Select a category" #ref="sfDropDown" DataSource="categories" CssClass="inputItem half-width" #bind-Value="#(itemModel.Category)">
<DropDownListFieldSettings Text="name" Value="id" />
</SfDropDownList>*#
</div>
<div class="inputRow">
<CheckBox Checked="isChecked" Label="Suggest Dates This Should Be Active?" OnCheckChange="#(OnCheckChange)" SizeClass="one-third" Width="300px"></CheckBox>
#if (isChecked)
{
<DateTimePicker Label="Active From:" SelectedDate="#activeFrom" Width="450px" SizeClass="one-third"></DateTimePicker>
<DateTimePicker Label="Active To:" SelectedDate="#activeTo" Width="450px" SizeClass="one-third"></DateTimePicker>
}
</div>
<div class="inputRow">
<FileUploader MaxSize="#(MaxSize)" OnClearFiles="OnClearFiles" OnFileRemove="OnFileRemove" OnFileUpload="OnFileUpload" SizeClass="full-width" Width="400px"></FileUploader>
</div>
<RichTextEditor DeniedAttributes="#DeniedAttributes" text=#(itemModel.Content) Height="400px" Width="1600px"></RichTextEditor>
</div>
</ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
</div>
#if (ShowDialog)
{
<Dialog Title="Create News Item" message="#Message" OKText="#OKText" cancelText="#CancelText" OnClose="OnDialogClose">
</Dialog>
}
#code {
[CascadingParameter]
Task<AuthenticationState> authenticationStateTask { get; set; }
public string userName { get; set; }
private int MaxSize { get; set; }
private string title { get; set; }
private int selectedCategory { get; set; }
private string content { get; set; }
int count { get; set; }
private bool ShowDialog { get; set; } = false;
private string Message { get; set; } = "";
private string OKText { get; set; } = "";
private string CancelText { get; set; } = "";
public DateTime activeTo { get; set; }
public DateTime activeFrom { get; set; }
private bool isChecked { get; set; }
SaveNewsItemModel itemModel = new SaveNewsItemModel();
List<string> DeniedAttributes = new List<string>() {
"id", "title", "style"
};
Dictionary<string, object> textboxValidation = new Dictionary<string, object>(){
{"maxlength", "100"}
};
List<spGetNewsCategoriesResult> categories = new List<spGetNewsCategoriesResult>();
private async Task OnCheckChange(bool check)
{
isChecked = check;
StateHasChanged();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var authState = await authenticationStateTask;
var user = authState.User;
userName = user.Identity.Name;
var context = contextFactory.CreateDbContext();
var procedures = context.Procedures;
categories = await procedures.spGetNewsCategoriesAsync();
MaxSize = 15 * 1024 * 1024;
}
}
private List<ToolbarItemModel> Tools = new List<ToolbarItemModel>() {
new ToolbarItemModel()
{
Command = ToolbarCommand.Bold
},
new ToolbarItemModel()
{
Command = ToolbarCommand.Italic
},
new ToolbarItemModel()
{
Command= ToolbarCommand.Underline
},
new ToolbarItemModel()
{
Command= ToolbarCommand.Separator
},
new ToolbarItemModel()
{
Command = ToolbarCommand.Undo
},
new ToolbarItemModel()
{
Command = ToolbarCommand.Redo
},
new ToolbarItemModel()
{
Command= ToolbarCommand.Separator
},
new ToolbarItemModel()
{
Command = ToolbarCommand.OrderedList
},
new ToolbarItemModel()
{
Command = ToolbarCommand.UnorderedList
},
new ToolbarItemModel()
{
Command = ToolbarCommand.Separator
},
new ToolbarItemModel()
{
Command = ToolbarCommand.FontColor
},
new ToolbarItemModel()
{
Command = ToolbarCommand.CreateLink
},
new ToolbarItemModel()
{
Command = ToolbarCommand.RemoveLink
}
};
private async Task OnFileUpload(UploadChangeEventArgs args)
{
foreach (var file in args.Files)
{
var fileName = file.FileInfo.Name;
using (var ms = file.Stream)
{
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
int count = 1;
string tempFileName = fileName;
while (fileService.TempFileExists(tempFileName))
{
tempFileName = $"({count}) {fileName}";
count++;
}
var bytes = ms.ToArray();
await fileService.SaveFileToTempAsync(bytes, tempFileName);
var mimetype = fileInfo.Extension;
itemModel.AddFile(fileName, mimetype, tempFileName, contextFactory);
}
}
}
private async Task OnClearFiles(ClearingEventArgs args)
{
foreach (var file in args.FilesData)
{
var fileName = file.Name;
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
itemModel.RemoveFile(fileName, fileInfo.Extension, contextFactory, fileService);
}
}
private async Task OnFileRemove(RemovingEventArgs args)
{
foreach (var file in args.FilesData)
{
var fileName = file.Name;
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
itemModel.RemoveFile(fileName, fileInfo.Extension, contextFactory, fileService);
}
}
private async Task OnSelectedItemChanged(ChangeEventArgs<int, spGetNewsCategoriesResult> eventArgs)
{
itemModel.Category = eventArgs.Value;
StateHasChanged();
}
private async Task OnSave()
{
if (isChecked)
{
itemModel.RequestDates(activeFrom, activeTo);
}
var context = contextFactory.CreateDbContext();
var procedures = context.Procedures;
var addedFiles = await procedures.spCreateNewsItemAsync(JsonConvert.SerializeObject(itemModel), userName);
if (addedFiles.Count > 0)
{
foreach (var file in addedFiles)
{
await fileService.MoveTempToNewsAsync(file.fileName, file.newsID, file.fileID);
}
}
Message = "This has been successfully saved and is now pending review; pressing OK will refresh the page.";
OKText = "OK";
ShowDialog = true;
}
private async Task OnDialogClose(bool r)
{
ShowDialog = false;
NavManager.NavigateTo(NavManager.Uri, true);
}
}
My issue is that I'm getting an error at this point: OnSelectedItemChanged="#(OnSelectedItemChanged)"
The error is:
Cannot convert from method group to EventCallback
The hunting I've done seems to imply that I need to explicitly pass the type in as a parameter, instead of using object and trying to infer it at runtime - I'm just a bit woolly on the details of how to do that?
TValue being an int is something that shouldn't change anywhere. But the TItem could be just about anything (in this particular scenario it's a spGetNewsCategoriesResult) - how do I cater for that?
After much hunting and tinkering, I've found the solution. By changing the component to this:
#typeparam T
<div class="inputItem #(SizeClass) dropdown" style="min-width:#(Width);">
<SfDropDownList TItem="T" TValue="int" Placeholder="Select a category" DataSource="DataSource" Value="#(SelectedItem)" EnableVirtualization="true">
<DropDownListEvents TItem="T" TValue="int" ValueChange="#OnSelectedItemChanged"></DropDownListEvents>
<DropDownListFieldSettings Text="#(TextField)" Value="#(ValueField)" />
</SfDropDownList>
</div>
#code {
[Parameter]
public IEnumerable<T> DataSource { get; set; }
[Parameter]
public EventCallback<Syncfusion.Blazor.DropDowns.ChangeEventArgs<int, T>> OnSelectedItemChanged { get; set; }
[Parameter]
public string Placeholder { get; set; }
[Parameter]
public string TextField { get; set; }
[Parameter]
public int SelectedItem { get; set; }
[Parameter]
public string ValueField { get; set; }
[Parameter]
public string Width { get; set; }
[Parameter]
public string SizeClass { get; set; }
}
And referencing it as such:
<DropDownList DataSource="categories" Placeholder="Select a category" SizeClass="half-width" Width="450px" TextField="name" ValueField="id" SelectedItem="#(itemModel.Category)" OnSelectedItemChanged="#(OnSelectedItemChanged)" T="spGetNewsCategoriesResult"></DropDownList>
The error is resolved. Decided to answer my own question as opposed to just deleting it because I figured it'll probably pop up for people on their own search.

ASP.Net MVC: How to show checkboxes selection in webgrid column after postback data

I have developed a tabular UI with webgrid. i am showing student information through webgrid. i am showing multiple checkboxes for hobbies in each row of webgrid. when i select hobbies and click submit button then i saw hobbies selection is not going to action.
i guess there is my mistake in view model class design. please have a look at my code and tell me which area i need to change in code.
i want all hobbies should go to action when i click submit button and selected hobbies also should post to action for each student. a student may have multiple hobbies selected.
here is my viewcode
#model MVCCRUDPageList.Models.StudentListViewModel
#{
ViewBag.Title = "Index";
}
<h2>Student View Model</h2>
#using (Html.BeginForm("Index", "WebGridMoreControls", FormMethod.Post))
{
var grid = new WebGrid(Model.Students, canSort: false, canPage: false);
var rowNum = 0;
var SelectedHobbies = 0;
<div id="gridContent" style=" padding:20px; ">
#grid.GetHtml(
tableStyle: "table",
alternatingRowStyle: "alternate",
selectedRowStyle: "selected",
headerStyle: "header",
columns: grid.Columns
(
grid.Column(null, header: "Row No", format: item => rowNum = rowNum + 1),
grid.Column("ID", format: (item) => #Html.TextBoxFor(m => m.Students[rowNum - 1].ID, new { #class = "edit-mode" })),
grid.Column("Name", format: (item) => #Html.TextBoxFor(m => m.Students[rowNum - 1].Name, new { #class = "edit-mode" })),
grid.Column("Country", format: (item) =>
#Html.DropDownListFor(x => x.Students[rowNum - 1].CountryID,
new SelectList(Model.Country, "ID", "Name", item.CountryID),
"-- Select Countries--", new { id = "cboCountry", #class = "edit-mode" })),
grid.Column(header: "Hobbies",
format: #<text>
Hobbies
#foreach (var hobby in Model.Hobbies)
{
<div class="checkbox">
<label>
#Html.HiddenFor(e => e.Hobbies)
<input type="checkbox"
name="Hobbies"
value="#hobby.ID" /> #hobby.Name
</label>
</div>
}
</text>)
))
<input type="submit" value="Submit" />
</div>
}
Action code
public class WebGridMoreControlsController : Controller
{
// GET: WebGridMoreControls
public ActionResult Index()
{
StudentListViewModel osvm = new StudentListViewModel();
return View(osvm);
}
[HttpPost]
public ActionResult Index(StudentListViewModel oStudentListViewModel)
{
return View(oStudentListViewModel);
}
}
View model code
public class StudentListViewModel
{
public IList<Student> Students { get; set; }
public List<Country> Country { get; set; }
public IList<Hobby> SelectedHobbies { get; set; }
public IList<Hobby> Hobbies { get; set; }
public StudentListViewModel()
{
Students = new List<Student>
{
new Student{ID=1,Name="Keith",CountryID=0,Hobby=0},
new Student{ID=2,Name="Paul",CountryID=2,Hobby=0},
new Student{ID=3,Name="Sam",CountryID=3,Hobby=0}
};
Country = new List<Country>
{
new Country{ID=1,Name="India"},
new Country{ID=2,Name="UK"},
new Country{ID=3,Name="USA"}
};
Hobbies = new List<Hobby>
{
new Hobby{ID=1,Name="Football"},
new Hobby{ID=2,Name="Hocky"},
new Hobby{ID=3,Name="Cricket"}
};
}
}
Model code
public class Student
{
public int ID { get; set; }
[Required(ErrorMessage = "First Name Required")]
public string Name { get; set; }
public int CountryID { get; set; }
public int Hobby { get; set; }
}
public class Country
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Hobby
{
public int ID { get; set; }
public string Name { get; set; }
}
please help me to rectify view, viewmodel and model class code. thanks
Add a viewmodel for Hobby:
public class HobbyViewModel
{
public int ID { get; set; }
public string Name { get; set; }
public bool Checked { get; set; }
}
Modify your StudentListViewModel as following:
public class StudentListViewModel
{
public IList<Student> Students { get; set; }
public List<Country> Country { get; set; }
public IList<HobbyViewModel> Hobbies { get; set; }
public StudentListViewModel()
{
Students = new List<Student>
{
new Student{ID=1,Name="Keith",CountryID=0,Hobby=0},
new Student{ID=2,Name="Paul",CountryID=2,Hobby=0},
new Student{ID=3,Name="Sam",CountryID=3,Hobby=0}
};
Country = new List<Country>
{
new Country{ID=1,Name="India"},
new Country{ID=2,Name="UK"},
new Country{ID=3,Name="USA"}
};
Hobbies = new List<HobbyViewModel>
{
new HobbyViewModel{ID=1,Name="Football"},
new HobbyViewModel{ID=2,Name="Hocky"},
new HobbyViewModel{ID=3,Name="Cricket"}
};
}
Replace the foreach in the view as following:
#for (var i = 0; i < Model.Hobbies.Count; i++)
{
<div class="checkbox">
#Html.HiddenFor(m => m.Hobbies[i].ID)
#Html.CheckBoxFor(m => m.Hobbies[i].Checked)
#Html.LabelFor(m => m.Hobbies[i].Checked, Model.Hobbies[i].Name)
</div>
}

AutoMapper mapping based on containing property name

Is it possible mapping two classes based on their similar property names:
class Source {
public int uId { get; set; }
public string PrefixRef { get; set; }
...
}
class Destination {
public int Id { get; set; }
public string Prefix { get; set; }
...
}
Thanks.
UPDATE:
-1, smart alek.
I'm totally new to AutoMapper.
Mapper.Initialize(cfg => {
cfg.RecognizePrefixes(new[] { "u" });
cfg.RecognizePostfixes(new[] { "Ref" });
cfg.CreateMap<Source, Destination>();
});

FullCalendar Day Light Savings renders wrong day and time

Ive been having this issue for a couple of days now and its something i cant seem to get past, If i post a one day event anytime during British Summer Time then the event when it renders in FullCalendar shows as a Two day event and puts the date back one hour and also moves the day (please see images below), the SQL is how it should be and showing the correct datetime but the calendar renders incorrectly.
I think that the issue is that the Json is coming out as ASP.net datetime and not ISO8601, I have tried all i can to change this but im new to .net and MVC so i just cant wrap my head around what to do.
I cant post a link to the picture of the event rendered as i dont have enough rep....
Pic of the data coming out in the object -
JsonObject
DB shot of the correct DateTime in SQL -
SQL DateTime
Heres how this setup is working for our MCV5 / FullCalendar project
Model -
public int Id { get; set; }
//Auto Populate
public string Subject { get; set; }
public string Description { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public bool? AllDay { get; set; }
public bool? isAMLeave { get; set; }
public bool? isPMLeave { get; set; }
public string ETADType { get; set; }
public string ETADSubType { get; set; }
[ForeignKey("AssignedRole")]
public int SelectRole { get; set; }
public bool? AllRoles { get; set; }
public int StaffID { get; set; }
public int EventStatus { get; set; }
/*Approval Details*/
public int? ApporovedId { get; set; }
public DateTime? ApprovedDate { get; set; }
public DateTime EventDate { get; set; }
/*soft audit*/
public double Duration { get; set; }
public string EventAction { get; set; }
public virtual AssignedRoles AssignedRole { get; set; }
}
JsonResult -
public JsonResult GetDiaryEventsDivOne()
{
if (User.IsInRole("Global Admin"))
{
var date = new Date(jsonDate);
var _DivisionOneList = from e in db.DiaryEvent
join lt in db.EventStatus on e.EventStatus equals lt.Id
join t in db.ETAD_EventTypes on e.ETADType equals t.ETADID.ToString()
join st in db.ETAD_EventSubType on e.ETADSubType equals st.ETADSubID.ToString()
join sid in db.AssignedRoles on e.StaffID equals sid.UserID
join tid in db.Teams on sid.TeamId equals tid.TeamID
join div in db.Divisions on sid.DivisionId equals div.DivisionID
join sd in db.SubDivisions on sid.SubDivisionId equals sd.SubDivisionID
join sp in db.JobRoles on sid.JobRoleID equals sp.JobRoleID
where div.DivisionID == 1
select new
{
id = e.Id,
title = e.Subject,
description = e.Description,
start = e.StartTime,
end = e.EndTime,
etad = t.ETADDescription.ToString(),
etadsub = st.Description.ToString(),
color = t.Colours.HexCode,
user = sid.StaffProfiles.Fullname,
jobtitle = sp.JobTitle.ToString(),
allroles = e.AllRoles,
division = div.DivisionName,
subdivision = sd.SubDivisionName,
allDay = false
};
var rows = _DivisionOneList.ToArray();
return Json(rows, JsonRequestBehavior.AllowGet);
And finally heres my JS
$(document).ready(function () {
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
eventSources: [
source1,
source2
],
timezone: 'Europe/London',
defaultView: 'month',
editable: false,
contentHeight: 700,
selectable: true,
eventClick: function (event, jsEvent, view) {
$("#startTime").html(moment(event.start).format('DD-MM-YYYY HH:mm'));
$("#endTime").html(moment(event.end).format('DD-MM-YYYY HH:mm'));
$('#modalTitle').html(event.title);
$('#user').text(event.user);
$('#modalBody').text(event.description);
$('#etad').html(event.etad);
$('#etadsub').html(event.etadsub);
$('#fullCalModal').modal('show');
$("#removeBtn").click(function () {
$.ajax({
type: 'POST',
url: "/BookingTwo/DeleteEvent",
data: {
"id": event.id
},
success: function () {
$('#calendar').fullCalendar('removeEvents', event.id);
$('#fullCalModal').modal('hide');
},
statusCode: {
202: function (reponose) {
$('#calendar').fullCalendar('refetchEvents');
$('#alert').addClass('alert alert-success').removeClass('alert-warning');
$("#alert").removeClass("hidden");
$("P").replaceWith("Success - Event Deleted")
$("#alert").fadeTo(5000, 500).slideUp(500, function () {
$('#alert').addClass("hidden");
})
},
409: function (reponse) {
$('#calendar').fullCalendar('refetchEvents');
$("#alert").removeClass("hidden");
$("P").replaceWith("Event already actioned.")
$("#alert").fadeTo(5000, 500).slideUp(500, function () {
$('#alert').addClass("hidden");
})
},
400: function (reponse) {
$('#calendar').fullCalendar('refetchEvents');
$("#alert").removeClass("hidden");
$("P").replaceWith("Access Denied - Not your leave request.")
$("#alert").fadeTo(5000, 500).slideUp(500, function () {
$('#alert').addClass("hidden");
})
}
}
});
});
},
Ive fixed the issue by setting
TimeZone; 'local'
I thought i had already set this in the paramaters but i had put Europe/London
For anyone having the same issue please look at your timezone settings in your JS for FullCalendar.

Sequence contains more than one matching element - composite key

When you try to create a one-to-many relationship from the use a composite key, I get the error "the sequence contains more than one matching element"
Help me please!
modelBuilder.Entity<PracticePilotScoringInfo>()
.HasKey(info => new { info.DriverName, info.Control,info.VehicleClass, info.ScoringInfoId });
modelBuilder.Entity<PracticeScoringInfo>()
.HasKey(info => info.Id)
.HasMany(info => info.PracticePilotScoringInfos)
.WithRequired(info => info.ScoringInfo)
.HasForeignKey(info => new { info.DriverName, info.Control, info.VehicleClass, info.ScoringInfoId });
public class PracticeScoringInfo : ScoringInfo
{
public int GrandPrixId { get; set; }
public GrandPrix GrandPrix { get; set; }
public virtual ICollection<PracticePilotScoringInfo> PracticePilotScoringInfos { get; set; }
}
public class PracticePilotScoringInfo : PilotScoringInfo
{
public string DriverName { get; set; }
public ControlType Control { get; set; }
public string VehicleClass { get; set; }
public Guid ScoringInfoId { get; set; }
public virtual PracticeScoringInfo ScoringInfo { get; set; }
}
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
Looks like I'm not identified in Fluent API mapping.
declaration a below is working fine
modelBuilder.Entity<ScoringInfo>()
.HasKey(info => info.Id);
modelBuilder.Entity<PracticeScoringInfo>()
.HasKey(info => info.Id);
modelBuilder.Entity<PilotScoringInfo>()
.HasKey(info => new { info.DriverName, info.Control, info.VehicleClass, info.ScoringInfoId });
modelBuilder.Entity<PracticePilotScoringInfo>()
.HasKey(info => new { info.DriverName, info.Control, info.VehicleClass, info.ScoringInfoId });

Resources