EF domain model
Hi there,
To reproduce the error, please do the following:
Attachment: GanttEF_5927fda1.zip
please provide an example of a fully featured domain model with all available properties of your Blazor GANTT component, which can be consumed bei EF (code first).
This one does not work and is incomplete, see attached example
To reproduce the error, please do the following:
- start VS2019 and load the solution
- PM > add-migration init
- PM > update-database -verbose
- start debugging using IIS Express
- add two tasks
- try to edit the task
Any ideas?
Cheers,
Volker
Volker
Attachment: GanttEF_5927fda1.zip
SIGN IN To post a reply.
14 Replies
LG
Logeswari Gopalakrishnan
Syncfusion Team
June 1, 2020 02:11 PM UTC
Hi Volker,
We analyzed the code snippet shared by you and we note that the error arises, as the primary key column(Id) was not defined in columns property. By default, id column will be act as a primary key column. Editing is performed based on this primary column. To avoid this issue, we can define the Id column in the GanttColumns property and make its visibility false. Please find the below code example.
|
<SfGantt ID="GanttExport" TValue="Table" Height="450px" Width="700px"
…///
<GanttColumns>
<GanttColumn Field=@nameof(Table.Id) Width="100" Visible="false"></GanttColumn>
</GanttColumns>
</SfGantt> |
Please find the below sample link.
Please let us know if you need further details on this.
Regards,
Logeswari G
VO
Volker
June 4, 2020 07:25 AM UTC
Hi Logeswari,
thank you, but I need a more detailed solution.
I need the same functionality like in this "Context Menu" example:
https://blazor.syncfusion.com/demos/gantt-chart/context-menu?theme=bootstrap4
BUT:
not hard-coded content as you did, but using EF Core consuming from SQL-Server:
thank you, but I need a more detailed solution.
I need the same functionality like in this "Context Menu" example:
https://blazor.syncfusion.com/demos/gantt-chart/context-menu?theme=bootstrap4
BUT:
not hard-coded content as you did, but using EF Core consuming from SQL-Server:
1) We must transfer your domain models to SQL Server entities:

2) We must be able to use all the functions of your context menu, but this time targeting to SQL-Server using EF Core:

3) We must be able to manage resources via checkboxes and send it to SQL-Server using EF Core:


Thanks for your help, it would be urgent ...
Cheers,
Volker
Cheers,
Volker
LG
Logeswari Gopalakrishnan
Syncfusion Team
June 5, 2020 03:16 AM UTC
Hi Volker,
Please find the below response.
|
S.No |
Queries |
Syncfusion Comments | |
|
1. |
We must transfer your domain models to SQL Server entities: |
By using hierarchal data , we can not perform operations on server-side. So we can use self-reference data binding. | |
|
2 |
We must be able to use all the functions of your context menu, but this time targeting to SQL-Server using EF Core: |
Currently we are working on this. We will provide the further details on June 8,2020. | |
|
3 |
We must be able to manage resources via checkboxes and send it to SQL-Server using EF Core: |
We can manage resources using dialog edit and changes are send to SQL- sever by changing collection of resources to string. Please find the below code snippet.
|
Please find the below sample link.
Please let us know, if you need further details on this.
Regards,
Logeswari G
VO
Volker
June 7, 2020 08:56 AM UTC
Hi Logeswari,
please clarify the difference between hierarchical (Child) and self-referential (ParentID) local data binding.
In other words: Do complex GANTT examples exist (just an image of the final diagram, no code needed), that you cannot create with ParentID, but only with Child? Or is it possible to construct every GANNT both with Child and with ParentID without restrictions?
Cheers,
Volker
please clarify the difference between hierarchical (Child) and self-referential (ParentID) local data binding.
In other words: Do complex GANTT examples exist (just an image of the final diagram, no code needed), that you cannot create with ParentID, but only with Child? Or is it possible to construct every GANNT both with Child and with ParentID without restrictions?
Cheers,
Volker
LG
Logeswari Gopalakrishnan
Syncfusion Team
June 8, 2020 03:29 PM UTC
Hi Volker,
Query 1:
For Hierarchical data binding, Child property is used to map the child records in hierarchical data. For self-referential data , ParentID property is used to map the child records. Please refer the below UG link to get more details about data binding in Gantt Chart.
UG link: https://blazor.syncfusion.com/documentation/gantt-chart/data-binding/?no-cache=1#data-binding
We can not bind both Hierarchical data binding (Child) and self-referential data (ParentID) to construct Gantt Chart.
Query 2: We must be able to use all the functions of your context menu, but this time targeting to SQL-Server using EF Core
We can use all functions of contextMenu and changes can be send to SQL-Server. Please find the below code snippet.
|
public override object BatchUpdate(DataManager dm, object changedRecords, object addedRecords, object deletedRecords, string keyField, string key, int? dropIndex)
{
List<GanttData> addRecord = addedRecords as List<GanttData>;
…//////
if (addRecord != null)
{
for (var i = 0; i < addRecord.Count(); i++)
{
var added = addRecord[i];
var newRecord = new Table {
Id = added.Id,
Name = added.Name,
Sdate = added.Sdate,
Edate = added.Edate,
Progress = added.Progress,
ParentId = added.ParentId,
ResourceId = added.ResourceId == null ? "" : UpdateResourceID(added.ResourceId)
};
db.Add<Table>(newRecord);
db.SaveChanges();
}
}
return (new { addedRecords = addRecord, changedRecords = changed, deletedRecords = deleteRecord });
} |
Please find the below sample link.
Please let us know, if you need further details on this.
Regards,
Logeswari G
VO
Volker
June 8, 2020 03:44 PM UTC
Hi Logeswari,
ad Query 1:
I really studied your documents believe me, before contacting the support ;-)
And I really studied that, too:
https://blazor.syncfusion.com/documentation/gantt-chart/data-binding/?no-cache=1#data-binding
https://blazor.syncfusion.com/documentation/gantt-chart/data-binding/?no-cache=1#data-binding
Of cause you cannot use both Child and ParentId in the same GANTT, that makes no sense and that was not the question, but:
The question was:
"Please clarify the difference between hierarchical (Child) and self-referential (ParentID) local data binding.
In other words: Do complex GANTT examples exist (just an image of the final diagram, no code needed), that you cannot create with ParentID, but only with Child or the other way round? Or is it possible to construct every GANNT both with Child and alternatively also with ParentID without restrictions?"
ad Query 2:
I'll try to implement your solution this way and will inform you if I was successful. Thanks!
ad Query 2:
I'll try to implement your solution this way and will inform you if I was successful. Thanks!
Cheers,
Volker
LG
Logeswari Gopalakrishnan
Syncfusion Team
June 9, 2020 02:57 PM UTC
Hi Volker,
In local data binding, the data source for rendering the Gantt control is retrieved from the same application locally.
|
S.no |
Hierarchical data binding |
self-referential data binding | ||
|
1. |
In hierarchical data binding subtasks or child tasks collections are identified by using Child property. |
Gantt can be rendered from self-referential data structures, by mapping the Id and ParentID fields. | ||
|
2. |
DataSouce:
|
DataSource:
| ||
|
3. |
TaskFields:
|
TaskFields:
| ||
|
4. |
Sample link for Hierarchical data binding:
|
Sample link for Flat data:
|
Please let us know, if you need further details on this.
Regards,
Logeswari
VO
Volker
June 16, 2020 02:43 PM UTC
Hi Logeswari,
thank you for your help.
Well, I tested your solution (GanttEF39685192.zip) deeply within the last days.
There is a huge conceptionel problem, which drives me crazy (see point 2 und 3).
To explain the problem I've made a simple test-setup based on GanttEF39685192.zip, so that you can reproduce the 3 problems, see attachend ZIP.
To reproduce the errors, please do the following:
- start VS2019 and load the solution
- PM > add-migration init
- PM > update-database -verbose
- Run the frontend and add a view tasks on page "gantt" so that there is some data in the db.
Everything works fine so far. Alternatively use this sql to create the table:
USE [Gantt-Test]
GO
CREATE TABLE [dbo].[GanttTasks](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NULL,
[Sdate] [datetime] NULL,
[Edate] [datetime] NULL,
[Progress] [nchar](10) NULL,
[ParentId] [int] NULL,
[Duration] [nchar](10) NULL,
[Dependency] [nvarchar](100) NULL,
CONSTRAINT [PK_GanttTasks] PRIMARY KEY CLUSTERED
( [Id] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] )
ON [PRIMARY]
GO
Preface:
As you can see, we have access to the DB both from "Home" and from "Gantt".
Please keep in mind that these two pages use different DbContexts (one is a DI-service via StartUp.cs, the other one is hardcoded in the DataAccessLayer).
Home:

Gantt:

Please keep in mind that these two pages use different DbContexts (one is a DI-service via StartUp.cs, the other one is hardcoded in the DataAccessLayer).
Home:
Gantt:
So these are the three problems with your solution:
(1) Version
I tested the solution with v18.1.0.56, everything worked fine.
I tested the solution with v18.1.0.56, everything worked fine.
When upgrading today to v18.1.0.57 my example (and the example you provided) doesn't work any longer:
So all BatchUpdates within CustomAdaptor are broken (try to modify an existing task, change dates or add a child via context menu).
There seems to be a bug within the latest release v18.1.0.57.
Anyway let's roll back to v18.1.0.56 and go on with the demonstration...
(2) hardcoded DB connection
In the Frontend there is no EntityFramework and db-stuff, just the GUI.
All database stuff is outsourced to the DataAccessLayer.
In DataAccessLayer there is my CustomAdaptor which derives from DataAdaptor.
Because you choose this approach in CustomAdaptor...
GanttManager.cs

...we must init a new DbContext using OnConfiguring:
GanttContext.cs

In the Frontend there is no EntityFramework and db-stuff, just the GUI.
All database stuff is outsourced to the DataAccessLayer.
In DataAccessLayer there is my CustomAdaptor which derives from DataAdaptor.
Because you choose this approach in CustomAdaptor...
GanttManager.cs
...we must init a new DbContext using OnConfiguring:
GanttContext.cs
The problem here is that the connection to SQL-Server is hardcoded in the backend rather than using the connectionstring from the Frontend's appsetting.json.
That's a massive problem to production scenarios.
appsettings.json
We must (!) use the connection string of FrontEnd to configure the backend (DataAccessLayer) and your CustomAdaptor.
Please modify the example to reach this goal!
(3) Multiple DbContexts
As I demonstrated on the index-page we have conventional access to the database using GanttContext and DI as we normally inject things as a service.
Startup.cs:

Index.razor:

As I demonstrated on the index-page we have conventional access to the database using GanttContext and DI as we normally inject things as a service.
Startup.cs:
Index.razor:
Cool!
But in your CustomAdaptor you add another DBContext...
GanttManager.cs

But in your CustomAdaptor you add another DBContext...
GanttManager.cs
Not cool!
So instead of using the DbContext of Frontend's Startup.cs service (DI, connectionstring, appsettings.json) we add a second one here.
That is dangerous and can cause concurency exceptions in FrontEnd on editing, when there is a grid, a dialog and a Gantt-diagram (with editing enabled) on the same page.
So it would be safer to use the one and only global DbContext defined in Startup.cs for the whole solution and not add additional ones for each Gantt-diagram in the DAL.
Startup.cs:

Startup.cs:
Please modify your example to reach this goal!
Cheers,
Volker
Attachment: Example_5_826c8a32.rar
LG
Logeswari Gopalakrishnan
Syncfusion Team
June 18, 2020 06:30 PM UTC
Hi Volker,
Please find the below response.
Query 1: When upgrading today to v18.1.0.57 my example (and the example you provided) doesn't work any longer:
So all BatchUpdates within CustomAdaptor are broken (try to modify an existing task, change dates or add a child via context menu).
There seems to be a bug within the latest release v18.1.0.57.
Ans: We are also able reproduce the issue with latest version . We will provide further details on June 19, 2020.
Query 2: hardcoded DB connection
Ans:
We have to include appsettings.json file and need to read that connection from OnConfiguring method of context file. Then In appsettings file need to add connection string. Please find the below code snippet.
|
[masterContext.cs]
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json")
.Build();
optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
}
}
[app.settings.json]
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLOCALDB; Database=MT; Trusted_Connection=True; MultipleActiveResultSets=true"
}
}
|
Please refer the following stack overflow link:
Please find the below sample link:
Query 3: Multiple DbContexts
Ans: We will provide further details on June 19, 2020.
Please let us know, if you need further details on this.
Regards,
Logeswari G
LG
Logeswari Gopalakrishnan
Syncfusion Team
June 23, 2020 12:55 PM UTC
Hi Volker,
Sorry for the inconvenience caused.
Please find the below response.
Query 1: When upgrading today to v18.1.0.57 my example (and the example you provided) doesn't work any longer:
So all BatchUpdates within CustomAdaptor are broken (try to modify an existing task, change dates or add a child via context menu).
There seems to be a bug within the latest release v18.1.0.57.
The reported issue was fixed in the latest version. Can you please upgrade Gantt packages to the latest version v18.1.0.59 and check?
We have prepared sample with updated packages. Please find it from below sample link.
Query 3: Multiple DbContexts
We have achieved this by creating CustomAdaptor as component and created this from DataAdaptor class and can access this service using Service property. Please find the below code snippet.
|
[Index.razor]
<SfGantt ID="GanttExport" TValue="Table" Height="450px" Width="700px">
<SfDataManager Adaptor="Adaptors.CustomAdaptor">
<CustomComponent></CustomComponent>
</SfDataManager>
</SfGantt>
[CustomComponent.razor]
@inherits DataAdaptor<masterContext>
@code {
// Performs data Read operation
public override object Read(DataManagerRequest dm, string key = null)
{
int count = Service.Table.Cast<Table>().Count();
return dm.RequiresCounts ? new DataResult() { Result = Service.Table, Count = count } : (object)Service.Table;
}
// Performs CRUD operation
public override object BatchUpdate(DataManager dm, object changedRecords, object addedRecords, object deletedRecords, string keyField, string key, int? dropIndex)
{
List<Table> addRecord = addedRecords as List<Table>;
List<Table> changed = changedRecords as List<Table>;
List<Table> deleteRecord = deletedRecords as List<Table>;
if (changed != null)
{
for (var i = 0; i < changed.Count(); i++)
{
var value = changed[i];
Table result = Service.Table.Where(or => or.Id == value.Id).FirstOrDefault();
result.Id = value.Id;
result.Name = value.Name;
result.Sdate = value.Sdate;
result.Edate = value.Edate;
result.Duration = value.Duration;
result.Progress = value.Progress;
Service.SaveChanges();
}
}
if (deleteRecord != null)
{
for (var i = 0; i < deleteRecord.Count(); i++)
{
Service.Table.Remove(Service.Table.Where(or => or.Id == deleteRecord[i].Id).FirstOrDefault());
Service.SaveChanges();
}
}
if (addRecord != null)
{
for (var i = 0; i < addRecord.Count(); i++)
{
Service.Table.Add(addRecord[i] as Table);
Service.SaveChanges();
}
}
return (new { addedRecords = addRecord, changedRecords = changed, deletedRecords = deleteRecord });
}
}
|
And in FetchData.razor file we have conventional access to the database using masterContext as we normally inject things as a service. Please find the below code snippet.
|
[FetchData.razor]
@using GanttEF.Models
@if (Table is null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Sdate</th>
<th>Edate</th>
</tr>
</thead>
<tbody>
@foreach (var task in Table)
{
<tr>
<td>@task.Id</td>
<td>@task.Name</td>
<td>@task.Sdate</td>
<td>@task.Edate</td>
</tr>
}
</tbody>
</table>
}
@code{
[Inject]
protected masterContext db { get; set; }
IQueryable<Table> Table;
protected override void OnInitialized()
{
Table = db.Table;
}
} |
Now we can use this Context for whole solution, no need to create addition Context. We have modified our sample for this. Please find the below sample link.
Please let us know, if you need further details on this.
Regards,
Logeswari G
VO
Volker
June 24, 2020 10:38 AM UTC
Hi Logeswari,
very nice solution.
Thank you very much!
Cheers,
Volker
Thank you very much!
Cheers,
Volker
LG
Logeswari Gopalakrishnan
Syncfusion Team
June 25, 2020 05:06 AM UTC
Hi Volker,
Most welcome.
Please get back to us if you would require further assistance on this.
Regards,
Logeswari G
VO
Volker
July 3, 2020 09:44 AM UTC
Hi Logeswari,
Do you think it makes sense to upgrade your CustomComponent.razor-component, so it gets thread-safe (ReadAsync BatchUpdateAsync)?
If so, could you provide an example?
This is my implemention:


This is my SQL-data, pretty straight forward:
Basically I copied StartDate to BaselineStartDate and EndDate to BaselineEndDate:

Then we wire things up like:

This is the output using your CustomComponent.razor.
Please mind the orange parent tasks' base-line dates and compare it to SQL data!

Zooming in shows it even better:
We can even simplify the behaviour.
Lets use the same SQL-data-source (!) for both StartDate/BaselineStartDate and EndDate/BaselineEndDate:

Orange things do not match!

So I'm not able to auto-refresh the gannt-diagram (MyGannt.Refresh()) after inserting things using the context menu or the dialog.

Any idea?
Cheers,
Volker
Attachment: EFCoreIdendityProblem_d7ef2ccb.zip
how are you doing?
Thank you so much for your help so far.
Anyway, some strange things are happening right now. Possibly there is a bug in your component:
Thank you so much for your help so far.
Anyway, some strange things are happening right now. Possibly there is a bug in your component:
1) Async
Concerning CustomAdaptor and SQL-Server (GanttEF2092535159.zip), this is no bug, just an suggestion.
Do you think it makes sense to upgrade your CustomComponent.razor-component, so it gets thread-safe (ReadAsync BatchUpdateAsync)?
If so, could you provide an example?
2) Baselines
First of all, thank you for this sample link: https://www.syncfusion.com/downloads/support/directtrac/general/ze/GanttEF2092535159
Based on your solution I made a test and found a strange display-behaviour of baselines
This is my implemention:
Let's reproduce the behaviour...
Example A)
This is my SQL-data, pretty straight forward:
Basically I copied StartDate to BaselineStartDate and EndDate to BaselineEndDate:
Then we wire things up like:
This is the output using your CustomComponent.razor.
Please mind the orange parent tasks' base-line dates and compare it to SQL data!
Zooming in shows it even better:
Some tasks' baseline-dates are shifted to the right, although SQL-data is still correct and unchanged (SSMS).

Example B)
We can even simplify the behaviour.
Lets use the same SQL-data-source (!) for both StartDate/BaselineStartDate and EndDate/BaselineEndDate:
Orange things do not match!
3) IDs
I've observed a strange behaviour concerning Ids of tasks.
Please have a look at the demo video, which shows the problem clearly.
Please have a look at the demo video, which shows the problem clearly.
- First I refresh the table (SSMS, right side) to show the actuaI IDs of all rows before we start the test.
- Then I insert a new task (Gantt-diagram) by clicking on an existing task, e.g. ID 3025 (left side).
- Then we get a new row showing ID 4048 in the diagram.
- Then I refresh the table in SSMS and we see there is a new recordset on the bottom with an ID 5076.
- Finally I refresh the diagram using MyGannt.Refresh() and only then the new task is displayed with its correct ID 5076.
So I'm not able to auto-refresh the gannt-diagram (MyGannt.Refresh()) after inserting things using the context menu or the dialog.
Of cause we cannot use OnActionComplete, cause this event is not fired exclusively when adding things or closing the context menu.
fyi:

4) Add a final task
Last but not least I found out that it's not possible to add a task using context-menu (1) or taskmenue item Add (2) of the very last task at the bottom (the one with the highest ID number).
When I press e.g. "Add Below" nothing happens. This only doesn't work with the very last rendered task of a diagram (in this case ID4047), on all other tasks this problem does not occure.

When I press e.g. "Add Below" nothing happens. This only doesn't work with the very last rendered task of a diagram (in this case ID4047), on all other tasks this problem does not occure.
Any idea?
Cheers,
Volker
Attachment: EFCoreIdendityProblem_d7ef2ccb.zip
PP
Pooja Priya Krishna Moorthy
Syncfusion Team
July 3, 2020 03:17 PM UTC
Hi Volker,
We have created a new incident under your account. Please use your direct trac account for further follow up.
Regards,
Pooja K.
SIGN IN To post a reply.
- 14 Replies
- 3 Participants
-
VO Volker
- May 29, 2020 03:28 PM UTC
- Jul 3, 2020 03:17 PM UTC