Creating an Entity Framework model from JSON Object - entity-framework

Using the following JSON object I want to create models in EF and their navigation properties also need model.Builder Entity
Also need information on one to many relation using the json specified below and using migrations create database tables.
[{
"Title": "AC",
"IconClass": "ac",
"Departments": "Housekeeping,Maintenance",
"Status": "NotInOrder",
"Parts": [{
"Title": "Power",
"IconClass": "power",
"Departments": "Housekeeping,Maintenance",
"Status": "NotInOrder",
"DependentUpon": "",
"Id": null
}, {
"Title": "Remote",
"IconClass": "remote",
"Departments": "Housekeeping,Maintenance",
"Status": "CleanedMaintained",
"DependentUpon": "Power",
"Id": null
}, {
"Title": "Cooling",
"IconClass": "cooling",
"Departments": "Housekeeping,Maintenance",
"Status": "CleanedMaintained",
"DependentUpon": "Remote",
"Id": null
}],
},
{
"Title": "TV",
"IconClass": "tv",
"Departments": "Housekeeping,Maintenance",
"Status": "CleanedMaintained",
"Parts": [{
"Title": "Power",
"IconClass": "power",
"Departments": "Housekeeping,Maintenance",
"Status": "CleanedMaintained",
"DependentUpon": "",
"Id": null
},
{
"Title": "TV - Remote",
"IconClass": "remote",
"Departments": "Housekeeping,Maintenance",
"Status": "CleanedMaintained",
"DependentUpon": "Power",
"Id": null
}]
]

According to your JSON object, your Entity Framework model classes should be as follows:
public class Product
{
[Key]
public int ProductId {get; set;}
public string Title { get; set; }
public string IconClass { get; set; }
public string Departments { get; set; }
public string Status { get; set; }
public ICollection<Part> Parts { get; set; }
}
public class Part
{
[Key]
public string Id { get; set; }
[ForeignKey("Product")]
public int ProductId {get; set;}
public string Title { get; set; }
public string IconClass { get; set; }
public string Departments { get; set; }
public string Status { get; set; }
public string DependentUpon { get; set; }
public Product Product {get; set;}
}
Then the DbContext:
public class YourDbContext : DbContext
{
public YourDbContext () : base("name=DefaultConnection")
{
}
public static YourDbContext Create()
{
return new YourDbContext ();
}
public DbSet<Product> Products { get; set; }
public DbSet<Part> Parts { get; set; }
}

Related

My Azure Function App is Returning 404 Not Found

I'm working my way through the book "Mastering Xamarin.Forms" by Ed Snider, which is overall an excellent book. However, I've run into a snag in creating an Azure function app as described in the book. I created the function app (MyTripLogFunctionApp) and a function within it called entry, and I see both of them on portal.azure.com. However, when I try to connect to it from a REST console (I'm using Talend API Tester), I get a 404 error. The URL I'm inputting is, as described in the book, https://mytriplogfunctionapp.azurewebsites.net/api/entry. In Talend API Tester, I set the entry to GET, click on Send, and 404! I've poked around on the web and verified that the version is set to 3, and the function app is set to 64-bit, but no joy. The book is 2 years old, so something may have changed. Anything wrong with how I'm going about this? Here's the code for the entry function:
#r "Newtonsoft.Json"
#r "Microsoft.WindowsAzure.Storage"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using Newtonsoft.Json;
public static async Task<IActionResult> Run(HttpRequest req, Newtonsoft.Json.Linq.JArray entryTableInput,
IAsyncCollector<Entry> entryTableOutput, ILogger log)
{
//log.LogInformation("C# HTTP trigger function processed a request.");
log.LogInformation(req.Method);
if(req.Method == "GET")
{
return (ActionResult) new OkObjectResult(entryTableInput);
}
var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
var entry = JsonConvert.DeserializeObject<Entry>(requestBody);
if(entry != null)
{
await entryTableOutput.AddAsync(entry);
return (ActionResult) new OkObjectResult(entry);
}
return new BadRequestObjectResult("Invalid entry request.");
}
public class Entry{
public string Id => Guid.NewGuid().ToString("n");
public string Title {get; set;}
public double Latitude {get; set;}
public double Longitude {get; set;}
public DateTime Date {get; set;}
public int Rating {get; set;}
public string Notes {get; set;}
public string PartitionKey => "ENTRY";
public string RowKey => Id;
}
And here's the json:
{
"bindings": [
{
"authLevel": "anonymous",
"name": "req",
"type": "httpTrigger",
"direction": "in",
"methods": [
"get",
"post"
]
},
{
"name": "$return",
"type": "http",
"direction": "out"
},
{
"type": "table",
"name": "entryTableOutput",
"tableName": "entry",
"connection": "AzureWebJobsStorage",
"direction": "out"
},
{
"type": "table",
"name": "entryTableOutput",
"tableName": "entry",
"take": 50,
"connection": "AzureWebJobsStorage",
"direction": "in"
}
]
,
"disabled" : false
}

ASP.NET Core 2.1 Entity Framework Core Related Data Duplication

I'm trying to build an ASP.NET Core API which returns an object containing some of related, joined, data.
But when I call an Article model using Include(), it's mapped automatically by EF Core. Which is intended, but.. unexpected mapping is occurring.
EF Core produce fully mapped object for all objects so that too much data is generated.
For example, User model has Article property and when I call Article model, User property also contains Article object information. As a result, it returns a lot of duplicated data.
At the first time, I think it's coming from
https://learn.microsoft.com/en-us/ef/core/querying/related-data
Eager loading
Explicit loading
Lazy loading
But it wasn't.
I don't know how to configure EF Core not to map all the objects inside..
*Database Schema & Model
enter image description here
public class Topic
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[HiddenInput(DisplayValue = false)]
public int TopicId { get; set; }
[Required]
[StringLength(20, ErrorMessage = "Title cannot be longer than 20 characters.")]
public string Title { get; set; }
[StringLength(200, ErrorMessage = "Description cannot be longer than 200 characters.")]
public string Description { get; set; }
public byte[] Picture { get; set; }
public string PictureMimeType { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
public DateTime PostDate { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
public DateTime ModifyDate { get; set; }
[Display(Name = "Show")]
public bool ShowFlag { get; set; }
public int UserId { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
public class Article
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[HiddenInput(DisplayValue = false)]
public int ArticleId { get; set; }
[Required]
[StringLength(100, ErrorMessage = "Title cannot be longer than 100 characters.")]
public string Title { get; set; }
public string Content { get; set; }
[StringLength(10, ErrorMessage = "Category cannot be longer than 10 characters.")]
public string Category { get; set; } = "Free";
public byte[] Picture { get; set; }
public string PictureMimeType { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
public DateTime PostDate { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
public DateTime ModifyDate { get; set; }
public int ReadCount { get; set; }
[Required]
[Display(Name = "Show")]
public bool ShowFlag { get; set; }
public int TopicId { get; set; }
public virtual Topic Topic { get; set; }
public int UserId { get; set; }
public virtual User User { get; set; }
}
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[HiddenInput(DisplayValue = false)]
public int UserId { get; set; }
[StringLength(20, ErrorMessage = "Name cannot be longer than 20 characters.")]
public string Name { get; set; }
[StringLength(255, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.EmailAddress)]
[EmailAddress]
public string Email { get; set; }
[StringLength(20, ErrorMessage = "Title cannot be longer than 20 characters.")]
public string Title { get; set; }
[StringLength(20, ErrorMessage = "Phone number cannot be longer than 20 characters.")]
[DataType(DataType.PhoneNumber)]
public string Phone { get; set; }
[StringLength(100, ErrorMessage = "Address cannot be longer than 100 characters.")]
public string Address { get; set; }
[StringLength(100, ErrorMessage = "Introduction cannot be longer than 100 characters.")]
public string Introduction { get; set; }
[DataType(DataType.Date)]
public DateTime? Birthdate { get; set; }
public byte[] Picture { get; set; }
public string PictureMimeType { get; set; }
public virtual ICollection<Topic> Topics { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
*Controller Code
var article = await this._context.Articles
.Include(a => a.User)
.Include(a => a.Topic)
.SingleOrDefaultAsync(a => a.ArticleId == id);
*Duplicated Data
{
"articleId": 5,
"title": "Does TaskAll() really wait for all in any case?",
"content": null,
"category": "Threading",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-06-18T07:00:00",
"modifyDate": "2018-06-20T07:47:42.1854485",
"readCount": 101,
"showFlag": true,
"topicId": 1,
"topic": {
"topicId": 1,
"title": "C#",
"description": "About C#",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-05-28T07:00:00",
"modifyDate": "2018-05-28T23:36:04.701311",
"showFlag": true,
"userId": 1,
"user": {
"userId": 1,
"name": "",
"password": null,
"email": "",
"title": "Junior Programmer!!",
"phone": "",
"address": "",
"introduction": "Hey, I'm Jason, most motivated person to be a fullstack programmer! ",
"birthdate": null,
"picture": null,
"pictureMimeType": null,
"permissionId": 0,
"permission": null,
"topics": [],
"articles": [
{
"articleId": 5,
"title": "Does TaskAll() really wait for all in any case?",
"content": null,
"category": "Threading",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-06-18T07:00:00",
"modifyDate": "2018-06-20T07:47:42.1854485",
"readCount": 101,
"showFlag": true,
"topicId": 1,
"userId": 1
}
]
},
"articles": [
{
"articleId": 5,
"title": "Does TaskAll() really wait for all in any case?",
"content": null,
"category": "Threading",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-06-18T07:00:00",
"modifyDate": "2018-06-20T07:47:42.1854485",
"readCount": 101,
"showFlag": true,
"topicId": 1,
"userId": 1,
"user": {
"userId": 1,
"name": "",
"password": null,
"email": "",
"title": "Junior Programmer!!",
"phone": "",
"address": "",
"introduction": "Hey, I'm Jason, most motivated person to be a fullstack programmer! ",
"birthdate": null,
"picture": null,
"pictureMimeType": null,
"topics": [],
"articles": []
}
}
]
},
"userId": 1,
"user": {
"userId": 1,
"name": "",
"password": null,
"email": "",
"title": "Junior Programmer!!",
"phone": "",
"address": "",
"introduction": "Hey, I'm Jason, most motivated person to be a fullstack programmer! ",
"birthdate": null,
"picture": null,
"pictureMimeType": null,
"topics": [
{
"topicId": 1,
"title": "C#",
"description": "About C#",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-05-28T07:00:00",
"modifyDate": "2018-05-28T23:36:04.701311",
"showFlag": true,
"userId": 1,
"articles": [
{
"articleId": 5,
"title": "Does TaskAll() really wait for all in any case?",
"content": null,
"category": "Threading",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-06-18T07:00:00",
"modifyDate": "2018-06-20T07:47:42.1854485",
"readCount": 101,
"showFlag": true,
"topicId": 1,
"userId": 1
}
]
}
],
"articles": [
{
"articleId": 5,
"title": "Does TaskAll() really wait for all in any case?",
"content": null,
"category": "Threading",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-06-18T07:00:00",
"modifyDate": "2018-06-20T07:47:42.1854485",
"readCount": 101,
"showFlag": true,
"topicId": 1,
"topic": {
"topicId": 1,
"title": "C#",
"description": "About C#",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-05-28T07:00:00",
"modifyDate": "2018-05-28T23:36:04.701311",
"showFlag": true,
"userId": 1,
"articles": []
},
"userId": 1
}
]
}
}
Actually , there's no "duplicated" data .
When the following query executed :
var article = await this._context.Articles
.Include(a => a.User)
.Include(a => a.Topic)
.SingleOrDefaultAsync(a => a.ArticleId == id);
the sql behind the scene will be :
SELECT TOP(1)
[a].[ArticleId], [a].[Category], [a].[Content], [a].[ModifyDate], [a].[Picture], [a].[PictureMimeType], [a].[PostDate],[a].[ReadCount], [a].[ShowFlag], [a].[Title],
[a].[TopicId], [a].[UserId],
[a.Topic].[TopicId], [a.Topic].[Description], [a.Topic].[ModifyDate], [a.Topic].[Picture], [a.Topic].[PictureMimeType], [a.Topic].[PostDate], [a.Topic].[ShowFlag], [a.Topic].[Title],[a.Topic].[UserId],
[a.User].[UserId], [a.User].[Address], [a.User].[Birthdate], [a.User].[Email], [a.User].[Introduction], [a.User].[Name], [a.User].[Password], [a.User].[Phone], [a.User].[Picture], [a.User].[PictureMimeType], [a.User].[Title]
FROM [Article] AS [a]
INNER JOIN [Topics] AS [a.Topic] ON [a].[TopicId] = [a.Topic].[TopicId]
INNER JOIN [Users] AS [a.User] ON [a].[UserId] = [a.User].[UserId]
WHERE [a].[ArticleId] = #__id_0
The SQL will not load any extra records . Let's say a User has two articles :
Article1 : { ArticleId=1, UserId=1}
Article3 : { ArticleId=3, UserId=1}
The query above will load only one article .
When the records loaded into memory from server , EFCore knows there's a relationship of 1-to-many between User and Articles and just begins to set the user object as the navigation property of article . The same happens between User and Topic Entities. All these are finished in memory .
As you see , there's no extra records retrieved from database and no duplicated data in memory .
What makes you confused is the data that serialized to client . However ,it does make sense . As a plain string has no idea of reference / pointer , it's hard to represent the relationship between objects with json .
By the way , there's no need to decorate you Email property of User with two almost same attributes :
[DataType(DataType.EmailAddress)]
[EmailAddress]
public string Email { get; set; }
It will cause an error of "two same custom attributes" when migrating database.

Migration does not generate the name change of the properties when I use Npgsql.EntityFrameworkCore.PostgreSQL

I'm new at this. I'm developing a solution with a Core project ASP.NET Web Application (.NET Core) .
It generates the initial smooth migration : the database created in PostgreSQL with tables , keys and indexes. He added the seed properly.
I'm working on a project with the Code First option . When you run the command to add the migration, the file is generated with the code in the Up and Down methods but does not generate the syntax for change of name of the property .
I tried creating annotations on the one hand and the change of name of the property on the other, and the latter migration run the Up and Down methods are generated empty.
Original class:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ContosoUniversity.Models
{
public class Estudiante
{
public int ID { get; set; }
public string Apellido { get; set; }
public string PrimerNombre { get; set; }
public DateTime FechaInscripcion { get; set; }
public virtual ICollection<Inscripcion> Inscripciones { get; set; }
}
}
Modified class:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ContosoUniversity.Models
{
public class Estudiante
{
public int ID { get; set; }
[StringLength(50)]
public string Apellido { get; set; }
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("nombre")]
public string PrimerNombre { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime FechaInscripcion { get; set; }
public virtual ICollection<Inscripcion> Inscripciones { get; set; }
}
}
I ran dotnet ef migrations add FormatoEstudiante and dotnet ef update datababse. The result of migration is this:
using Microsoft.EntityFrameworkCore.Migrations;
namespace ContosoUniversity.Migrations
{
public partial class FormatoEstudiante : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "primernombre",
schema: "public",
table: "estudiante",
maxLength: 50,
nullable: true);
migrationBuilder.AlterColumn<string>(
name: "apellido",
schema: "public",
table: "estudiante",
maxLength: 50,
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "primernombre",
schema: "public",
table: "estudiante",
nullable: true);
migrationBuilder.AlterColumn<string>(
name: "apellido",
schema: "public",
table: "estudiante",
nullable: true);
}
}
}
Project.json:
{
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
},
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.0",
"Microsoft.AspNetCore.Razor.Tools": {
"version": "1.0.0-preview2-final",
"type": "build"
},
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0",
"Microsoft.Extensions.Logging": "1.0.0",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.Extensions.Logging.Debug": "1.0.0",
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
"Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0",
"Microsoft.EntityFrameworkCore": "1.0.0",
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.0",
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
"Microsoft.EntityFrameworkCore.Design": "1.0.0-preview2-final",
"Npgsql": "3.1.7",
"Npgsql.EntityFrameworkCore.PostgreSQL": "1.0.1"},
"tools": {
"BundlerMinifier.Core": "2.0.238",
"Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2- final",
"Microsoft.EntityFrameworkCore.Tools": {
"version": "1.0.0-preview2-final",
"imports": [
"portable-net45+win8+dnxcore50",
"portable-net45+win8"
]
}
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"net450",
"portable-net45+win8"
]
}
},
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"runtimeOptions": {
"configProperties": {
"System.GC.Server": true
}
},
"publishOptions": {
"include": [
"wwwroot",
"Views",
"Areas/**/Views",
"appsettings.json",
"web.config"
]
},
"scripts": {
"prepublish": [ "bower install", "dotnet bundle" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
}
Migration did not recognize the name change of the column. I do not know if it's a problem in the code or because EF Core with Npgsql still does not support annotation.
Any ideas?
Thank you...

Bidirectional OneToOne relationship in JPA-RS not traversable

I use the simple entities below for exploring jpa-rs:
#Entity
public class Employee {
#Id
#GeneratedValue
private int id;
private String name;
#OneToOne
private Address address;
}
#Entity
public class Address {
#Id
#GeneratedValue
private int id;
private String street;
private String city;
#OneToOne(mappedBy = "address")
private Employee employee;
}
Creating an Employee entity with an Address relation works like a charm:
{
"name": "John Doe",
"address": {
"street": "Street No. 1",
"city": "A City"
}
}
But i cannot travers the resulting objects by the _links, like HATEOAS proposes.
The provided students example in the Eclipselink wiki (http://wiki.eclipse.org/EclipseLink/Examples) allows this easily.
As far as i understand, i should be able to do the following:
fetch the employee with id 1: GET url/entity/Employee/1: {
"id": 1,
"name": "John Doe",
"_relationships": [
{
"_link": {
"href": "url/entity/Employee/1/address",
"rel": "address"
}
}
],
"address": {
"_link": {
"href": "url/entity/Address/2",
"method": "GET",
"rel": "self"
}
},
"staff": []
}
fetch the address of the employee: GET url/entity/Address/2:{
"city": "A City",
"id": 2,
"street": "Street No. 1",
"_relationships": [
{
"_link": {
"href": "url/entity/Address/2/employee",
"rel": "employee"
}
}
]
}
Now lets get back to the employee from here: GET url/entity/Address/2/employee -> http status 400
In the mentioned example i can flawlessly navigate using all the links for the relationship.
p.s.: I'd like to tag this JPA-RS, but i don't have enough reputation to create a new tag.

DataContract class for Facebook 'Like' Graph API

So I'm trying to decode the json returned by the Facebook Graph API for user likes into objects using the DataContractJsonSerializer. I've tried creating a couple different [DataContract] classes now but with no luck.
What is the correct way to create a [DataContract] class for this data.
{
"data": [
{
"name": "Earlyups",
"category": "Recreation/sports",
"id": "170410902986097",
"created_time": "2012-04-09T03:34:11+0000"
},
{
"name": "pictureline inc.",
"category": "Local business",
"id": "28861182380",
"created_time": "2012-03-28T02:02:24+0000"
},
{
"name": "Jackson Hole Mountain Resort",
"category": "Sports/recreation/activities",
"id": "24718308041",
"created_time": "2012-03-20T16:10:45+0000"
}
],
"paging": {
"next": "next_page_request_url"
}
}
haha, wow as soon as I posted I saw what I was doing wrong. In case anyone else is interested.
[DataContract]
internal class LikePage
{
[DataMember]
internal Like[] data;
[DataMember]
internal Paging paging;
}
[DataContract]
internal class Like
{
[DataMember]
internal string name;
[DataMember]
internal string category;
[DataMember]
internal string id;
[DataMember]
internal string created_time;
}
[DataContract]
internal class Paging
{
[DataMember]
internal string next;
}