Simple.Data > Object inside another object not populated - simple.data

I have 2 tables as below:
Table: Orders
CREATE TABLE [dbo].[orders](
[id] [int] IDENTITY(1,1) NOT NULL,
[ticker] [char](5) NOT NULL,
[broker_id] [char](12) NOT NULL,
[type] [smallint] NOT NULL,
[quantity] [int] NOT NULL,
[price] [money] NOT NULL,
CONSTRAINT [PK_orders] 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
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[orders] WITH CHECK ADD CONSTRAINT [FK_orders_quotes] FOREIGN KEY([ticker])
REFERENCES [dbo].[quotes] ([ticker])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[orders] CHECK CONSTRAINT [FK_orders_quotes]
GO
ALTER TABLE [dbo].[orders] WITH CHECK ADD CONSTRAINT [FK_orders_types] FOREIGN KEY([type])
REFERENCES [dbo].[order_types] ([id])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[orders] CHECK CONSTRAINT [FK_orders_types]
GO
ALTER TABLE [dbo].[orders] WITH CHECK ADD CONSTRAINT [FK_orders_users] FOREIGN KEY([broker_id])
REFERENCES [dbo].[users] ([id])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[orders] CHECK CONSTRAINT [FK_orders_users]
GO
Table: users
CREATE TABLE [dbo].[users](
[id] [char](12) NOT NULL,
[password] [varchar](60) NULL,
[first_name] [varchar](20) NULL,
[last_name] [varchar](20) NULL,
[email] [varchar](20) NULL,
[date_of_birth] [datetime] NULL,
[capital] [money] NULL,
[created_by] [varchar](12) NULL,
[created_date] [datetime] NULL,
CONSTRAINT [PK_users] 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
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[users] ADD DEFAULT ((0.0)) FOR [capital]
GO
And I have these 2 classes that map to the tables above:
Order
public class Order
{
public Order(string ticker, User user, OrderTypes type, int quantity, decimal price)
{
this.Ticker = ticker;
this.Broker = user;
this.Type = type;
this.Quantity = quantity;
this.Price = price;
}
public Order() { }
public string Ticker { get; private set; }
public OrderTypes Type { get; private set; }
public int Quantity { get; private set; }
public decimal Price { get; private set; }
public User Broker { get; private set; }
}
User
public class User
{
public User() { }
public User(string id, string firstName, string lastName, DateTime dateOfBirth, string email, decimal capital)
{
this.Id = id;
this.FirstName = firstName;
this.LastName = lastName;
this.DateOfBirth = dateOfBirth;
this.Email = email;
this.Capital = capital;
}
public User(string id, string firstName, string lastName, DateTime dateOfBirth, string email) : this(id, firstName, lastName, dateOfBirth, email, 0) { }
public string Id { get; private set; }
public string FirstName { get; private set; }
public string LastName { get; private set; }
public DateTime DateOfBirth { get; private set; }
public string Email { get; private set; }
public decimal Capital { get; private set; }
}
Finally, I have these two lines of code:
db.Orders.Insert(id: 1, broker_id: "john.doe", quantity: 100);
Order order = db.Orders.Get(1);
The object order has the properties "Id" and "Quantity" populated, but the object "Broker" is null.
So I tried to retrieve the data like shown below, but still no luck: the Broker object is always NULL:
var order = db.Orders.FindAllById(1)
.Join(db.Users.As("Broker"), out user)
.On(Id: db.Orders.Broker_Id)
.With(user.As("Broker"))
.FirstOrDefault();
WITH __Data AS (SELECT [dbo].[orders].[id], ROW_NUMBER() OVER(ORDER BY [dbo].[orders].[id]) AS [_#_]
from [dbo].[orders] JOIN [dbo].[users] [Broker] ON ([Broker].[id] = [dbo].[orders].[broker_id]) WHERE [dbo].[orders].[id] = #p1)
SELECT [dbo].[orders].[id],[dbo].[orders].[ticker],[dbo].[orders].[broker_id],[dbo].[orders].[type],[dbo].[orders].[quantity],[dbo].[orders].[price],[Broker].[id] AS [__withn__Broker__id],[Broker].[password] AS [__withn__Broker__password],[Broker].[first_name] AS [__withn__Broker__first_name],[Broker].[last_name] AS [__withn__Broker__last_name],[Broker].[email] AS [__withn__Broker__email],[Broker].[date_of_birth] AS [__withn__Broker__date_of_birth],[Broker].[capital] AS [__withn__Broker__capital],[Broker].[created_by] AS [__withn__Broker__created_by],[Broker].[created_date] AS [__withn__Broker__created_date] FROM __Data JOIN [dbo].[orders] ON [dbo].[orders].[id] = __Data.[id] JOIN [dbo].[users] [Broker] ON ([Broker].[id] = [dbo].[orders].[broker_id]) WHERE [dbo].[orders].[id] = #p1 AND [_#_] BETWEEN 1 AND 1
Parameters:
#p1 (Int32) = 1
order = db.Orders.FindAllById(1)
.Join(db.Users.As("Broker"), out user)
.On(db.Orders.broker_id == user.Id)
.With(user)
.FirstOrDefault();
WITH __Data AS (SELECT [dbo].[orders].[id], ROW_NUMBER() OVER(ORDER BY [dbo].[orders].[id]) AS [_#_]
from [dbo].[orders] JOIN [dbo].[users] [Broker] ON ([dbo].[orders].[broker_id] = [Broker].[id]) WHERE [dbo].[orders].[id] = #p1)
SELECT [dbo].[orders].[id],[dbo].[orders].[ticker],[dbo].[orders].[broker_id],[dbo].[orders].[type],[dbo].[orders].[quantity],[dbo].[orders].[price],[Broker].[id] AS [__withn__Broker__id],[Broker].[password] AS [__withn__Broker__password],[Broker].[first_name] AS [__withn__Broker__first_name],[Broker].[last_name] AS [__withn__Broker__last_name],[Broker].[email] AS [__withn__Broker__email],[Broker].[date_of_birth] AS [__withn__Broker__date_of_birth],[Broker].[capital] AS [__withn__Broker__capital],[Broker].[created_by] AS [__withn__Broker__created_by],[Broker].[created_date] AS [__withn__Broker__created_date] FROM __Data JOIN [dbo].[orders] ON [dbo].[orders].[id] = __Data.[id] JOIN [dbo].[users] [Broker] ON ([dbo].[orders].[broker_id] = [Broker].[id]) WHERE [dbo].[orders].[id] = #p1 AND [_#_] BETWEEN 1 AND 1
Parameters:
#p1 (Int32) = 1
order = db.Orders.With(db.Users.As("Broker")).Get(1);
WITH __Data AS (SELECT [dbo].[orders].[id], ROW_NUMBER() OVER(ORDER BY [dbo].[orders].[id]) AS [_#_]
from [dbo].[orders] WHERE [dbo].[orders].[id] = #p1)
SELECT [dbo].[orders].[id],[dbo].[orders].[ticker],[dbo].[orders].[broker_id],[dbo].[orders].[type],[dbo].[orders].[quantity],[dbo].[orders].[price] FROM __Data JOIN [dbo].[orders] ON [dbo].[orders].[id] = __Data.[id] WHERE [dbo].[orders].[id] = #p1 AND [_#_] BETWEEN 1 AND 1
Parameters:
#p1 (Int32) = 1
Note: when assigning the order to a type of variable "var", the order does have the user information populated.
So, if I do this:
var dynamicOrder = db.Orders.WithUser().Get(1);
the "dynamicOrder" is of type "Simple.Data.SimpleRecord" which has inside the following property "System.Collections.Generic.IDictionary.Values" that contains the "user" data inside.
So the issue appears to be with the casting of the user data to the user class.
Thoughts?

Related

JPA / Spring MVC Rest API - One to Many relation in the same Entity

I began 2 days ago to use Spring MVC and I meet some issues with a case study.
I created a basic table categories (category_id refers to a category id):
DROP TABLE IF EXISTS `categories`;
CREATE TABLE IF NOT EXISTS `categories` (
`id` int(11) NOT NULL,
`category_id` int(11) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK_CATEGORY_CATEGORY` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `categories`
ADD CONSTRAINT `FK_CATEGORY_CATEGORY` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`);
Now my issue is to display the full list of categories with their children if they exist ...
I have in my controller this method which returns a list in JSON :
#GetMapping(path="/categories", produces= {"application/json"})
public List<Category> getAllCategories(Model model) {
return categoryRepository.findAll();
}
It is recommended to do this :
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
#ManyToOne
private Category parentCategory;
#OneToMany(mappedBy="parentCategory", fetch = FetchType.EAGER)
private List<Category> childCategories;
... default constructor, getters & setter etc.
}
While trying to view the page i can see the categories but i don't display if they have subcategories or not .... For example this category shoud give a list of children categories ... For example i shoud have in child categories id = 5, name = ..., etc., id =6, id = 7...
{
"id": 1,
"name": "XXX",
"createdat": 1541872732000,
"updatedat": 1541872732000,
"parentCategory": null,
"childCategories": [
]
....
}
and this category who have a parent category returns no parent whereas the parentCategory value should be 1 :
{
"id": 14,
"name": "xxxxxx",
"createdat": 1541873447000,
"updatedat": 1541873447000,
"parentCategory": null,
"childCategories": [
]
....
}
Thanks for your help.
Here is the solution i found :
#Entity
#Table(name="categories")
#NamedQuery(name="Category.findAll", query="SELECT c FROM Category c")
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private Long id;
#Column(name="name")
private String name;
#ManyToOne(cascade={CascadeType.ALL})
#JoinColumn(name="category_id")
#JsonBackReference
private Category parentCategory;
#OneToMany(mappedBy="parentCategory", fetch = FetchType.EAGER)
#JsonManagedReference
private List<Category> childCategory;
public Category() {
}
public Category(String name) {
this.name = name;
}
// getters & setters
}

Android table creation Failure (while compiling: CREATE TABLE IF NOT EXISTS

While compiling:
CREATE TABLE IF NOT EXISTS `SeasonMasterDB`
(`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`id` TEXT PRIMARY KEY AUTOINCREMENT, `name` TEXT
);
that is why you are getting an error. Please help me, this is my code:
#Table(name = "SeasonMasterDB",database = AppDatabase.class)`enter code here`
public class SeasonMasterDB extends Model {
#PrimaryKey
public Long id;
#Column(name = "id")
public String idValue;
#Column(name = "name")
public String name;
public SeasonMasterDB()
{
}
public SeasonMasterDB(String name,String id)
{
this.idValue = id;
this.name = name;
}
}
You cannot have two columns with the same name. Rename one of your id columns.

Required and StringLength are ignored by ASP.NET MVC5 - EF6

I am using Visual Studio 2017 with a asp.net mvc 5 and entity framework 6. I am following an online course and the steps the author is doing, is creating 2 classes with properties, then marking properties as [Required] and assign [StringLength(255)] to some other string properties. The modifications work on one class but not on the other.
This is the code for the 2 classes:
The one that's working:
public class Genre
{
public byte Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
}
The one that's not working:
public class Gig
{
public int Id { get; set; }
[Required]
public ApplicationUser Artist { get; set; }
public DateTime DateTime { get; set; }
[Required]
[StringLength(255)]
public string Venue { get; set; }
[Required]
public Genre Genre { get; set; }
}
I ran migration first time before adding the attributes, and the CreateTables.cs migration looks like this:
public override void Up()
{
CreateTable(
"dbo.Genres",
c => new
{
Id = c.Byte(nullable: false),
Name = c.String(),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.Gigs",
c => new
{
Id = c.Int(nullable: false, identity: true),
DateTime = c.DateTime(nullable: false),
Venue = c.String(),
Artist_Id = c.String(maxLength: 128),
Genre_Id = c.Byte(),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.AspNetUsers", t => t.Artist_Id)
.ForeignKey("dbo.Genres", t => t.Genre_Id)
.Index(t => t.Artist_Id)
.Index(t => t.Genre_Id);
}
Then I added the attributes to my code, and added a new migration, When I run add migration, the generated code in the migration is like this:
public override void Up()
{
DropForeignKey("dbo.Gigs", "Artist_Id", "dbo.AspNetUsers");
DropForeignKey("dbo.Gigs", "Genre_Id", "dbo.Genres");
DropIndex("dbo.Gigs", new[] { "Artist_Id" });
DropIndex("dbo.Gigs", new[] { "Genre_Id" });
AlterColumn("dbo.Genres", "Name", c => c.String(nullable: false, maxLength: 255));
AlterColumn("dbo.Gigs", "Venue", c => c.String(nullable: false, maxLength: 255));
AlterColumn("dbo.Gigs", "Artist_Id", c => c.String(nullable: false, maxLength: 128));
AlterColumn("dbo.Gigs", "Genre_Id", c => c.Byte(nullable: false));
CreateIndex("dbo.Gigs", "Artist_Id");
CreateIndex("dbo.Gigs", "Genre_Id");
AddForeignKey("dbo.Gigs", "Artist_Id", "dbo.AspNetUsers", "Id", cascadeDelete: true);
AddForeignKey("dbo.Gigs", "Genre_Id", "dbo.Genres", "Id", cascadeDelete: true);
}
However, the generated T-SQL code to create the table is like this:
CREATE TABLE [dbo].[Gigs] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[DateTime] DATETIME NOT NULL,
[Venue] NVARCHAR (MAX) NULL,
[Artist_Id] NVARCHAR (128) NULL,
[Genre_Id] TINYINT NULL,
CONSTRAINT [PK_dbo.Gigs] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.Gigs_dbo.AspNetUsers_Artist_Id] FOREIGN KEY ([Artist_Id]) REFERENCES [dbo].[AspNetUsers] ([Id]),
CONSTRAINT [FK_dbo.Gigs_dbo.Genres_Genre_Id] FOREIGN KEY ([Genre_Id]) REFERENCES [dbo].[Genres] ([Id])
);
However, the generated TSQL for the other table, was right:
CREATE TABLE [dbo].[Genres] (
[Id] TINYINT NOT NULL,
[Name] NVARCHAR (255) NOT NULL,
CONSTRAINT [PK_dbo.Genres] PRIMARY KEY CLUSTERED ([Id] ASC)
);
Why the T-SQL is not reflecting the modifications by the migration for the 1st table? Knowing that I added the migration and executed update-database, and could see the changes for one table (Genre), but not the other.
Any help is appreciated.
I've faced the same problem, neither StringLength nor MaxLength Data Annotations didn't helped me much. It seems I'm trying to use same online course, which initially for MSVS2015, but I'm using latest MSVS2017.
What I've tried so far:
Setting length as is and the change only it in migration
Setting specific migration version with Update-Database -TargetMigration Migration
Setting all the migrations from scratch with Update-Database -TargetMigration 0 | Update-Database -Force
Recreating database (Deleting database in SQL Server Object Explorer)
And after all SQL definition still contains initial MAX constraint, as well as table definition.
Part of migration
AlterColumn("dbo.Genres", "Name", c => c.String(nullable: false, maxLength: 255));
AlterColumn("dbo.Gigs", "Venue", c => c.String(nullable: false, maxLength: 255));
AlterColumn("dbo.Gigs", "Artist_Id", c => c.String(nullable: false, maxLength: 128));
Database definition after all migrations
[Name] NVARCHAR (MAX) NULL,
...
[Venue] NVARCHAR (MAX) NULL,
[Artist_Id] NVARCHAR (128) NULL,

Error "EntityType has no key defined" for composite keys

I am trying to bind my data using entity framework v6.1.3 but I am getting this error message EntityType has no key defined. Define the key for this EntityType. (I am having a composite key)
I've tried the following approaches:
public class CommunicationCollection
{
[Key, Column(Order = 0)]
[ForeignKey("FK_CommunicationCollection_Communication")]
public Guid CommunicationId;
[Key, Column(Order = 1)]
[ForeignKey("FK_CommunicationCollection_Collection")]
public Guid CollectionId;
}
and this
public class CommunicationCollection
{
[Key, Column(Order = 0)]
[ForeignKey("FK_CommunicationCollection_Communication")]
public Guid CommunicationId;
[Key, Column(Order = 1)]
[ForeignKey("FK_CommunicationCollection_Collection")]
public Guid CollectionId;
public virtual Communication Communication { get; set; }
public virtual Collection Collection { get; set; }
}
and also this
public class CommunicationCollection
{
[Key, Column(Order = 0)]
public Guid CommunicationId;
[Key, Column(Order = 1)]
public Guid CollectionId;
}
and in the DB I have
CREATE TABLE [CommunicationCollection](
[CommunicationId] [uniqueidentifier] NOT NULL,
[CollectionId] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_CommunicationCollection] PRIMARY KEY CLUSTERED
(
[CommunicationId] ASC,
[CollectionId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [CommunicationCollection] WITH CHECK ADD CONSTRAINT [FK_CommunicationCollection_Collection] FOREIGN KEY([CollectionId])
REFERENCES [Collection] ([CollectionId])
GO
ALTER TABLE [CommunicationCollection] CHECK CONSTRAINT [FK_CommunicationCollection_Collection]
GO
ALTER TABLE [CommunicationCollection] WITH CHECK ADD CONSTRAINT [FK_CommunicationCollection_Communication] FOREIGN KEY([CommunicationId])
REFERENCES [Communication] ([CommunicationId])
GO
ALTER TABLE [CommunicationCollection] CHECK CONSTRAINT [FK_CommunicationCollection_Communication]
GO
Any idea what am I missing?
Thanks a lot!
With EF, everything needs to be properties and not just 'plain' variables. This is needed so EF can hook into those methods.
So like this:
public Guid CommunicationId { get; set; }
public Guid CollectionId { get; set; }
Forgetting to do this causes all kinds of problems that can be hard to trace back to the actual cause, as you have just encountered.

Cannot insert the value NULL into column error

I am attempting to save user preferences into a table but am getting a null exception and I do not understand why. This is an MVC 4 application and this is my action result where I am getting the error.
public ActionResult Go(string path, string name)
{
RaterContext r = new RaterContext();
UserData u = new UserData();
var userid = u.GetCurrentUserData().UserId;
var info = r.RatersInfo.Where(w => w.RaterName.Equals(name)).FirstOrDefault();
var pref = r.RatersPreferences.Where(w => w.RaterId.Equals(info.RaterId) && w.UserId.Equals(userid)).FirstOrDefault();
if (pref != null && pref.Count > 0)
{
pref.Count++;
r.SaveChanges();
}
else
{
pref = new RaterPreferences();
pref.UserId = userid;
pref.RaterId = info.RaterId;
pref.Count = 1;
r.RatersPreferences.Add(pref);
r.SaveChanges();
}
return Redirect(path);
}
There is nothing saved in the preferences table yet so it is hitting the else block and throwing a null exception on r.SaveChanges();. The exception is
Cannot insert the value NULL into column 'UserId', table
'WebSiteNew.dbo.RaterPreferences'; column does not allow nulls. INSERT
fails.\r\nThe statement has been terminated.
The reason this doesn't make sense is because all three properties, including the UserId have data when I step through. These are the only fields in the table. UserId = 1, RaterId = 6 and Count is clearly set to 1. They are all set as non-nullable ints and the primary key is a combination of UserId and RaterId. My Model is as follows.
public class RaterContext : DbContext
{
public RaterContext()
: base("DefaultConnection")
{
}
public DbSet<RaterInfo> RatersInfo { get; set; }
public DbSet<RaterPreferences> RatersPreferences { get; set; }
}
[Table("RaterInfo")]
public class RaterInfo
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int RaterId { get; set; }
public string RaterName { get; set; }
public string RaterLink { get; set; }
public string Section { get; set; }
public string Department { get; set; }
}
[Table("RaterPreferences")]
public class RaterPreferences
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public int RaterId { get; set; }
public int Count { get; set; }
}
Any help would be greatly appreciated as I am relatively new to MVC and ASP.NET. Let me know if you need more information. Thanks in advance!
I don't know if this helps but I tested to see what would happen on UPDATE by adding data manually so it would catch on the if block and that works. I'm only getting an error on INSERT.
Here is the create statement for the table in question.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[RaterPreferences](
[UserId] [int] NOT NULL,
[RaterId] [int] NOT NULL,
[Count] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[UserId] ASC,
[RaterId] 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
ALTER TABLE [dbo].[RaterPreferences] WITH CHECK ADD CONSTRAINT [FK_RaterPreferences_RaterInfo] FOREIGN KEY([RaterId])
REFERENCES [dbo].[RaterInfo] ([RaterId])
GO
ALTER TABLE [dbo].[RaterPreferences] CHECK CONSTRAINT [FK_RaterPreferences_RaterInfo]
GO
I have copied your code into a brand new ASP.Net MVC project with the current version of Entity Framework and I am able to run your code with no problems. I escaped the UserData acquisition with code that looks like:
RaterContext r = new RaterContext();
//UserData u = new UserData();
var userid = 1; // u.GetCurrentUserData().UserId;
var info = r.RatersInfo.Where(w => w.RaterName.Equals(name)).FirstOrDefault();
and did not have a problem running the remainder of this code.
I think you may have some problems with your keys and database structure for the RaterPreferences table. I don't know your full data-model, but I don't understand how this fits in, and it is not keyed in your code the way that you describe.
Edit:
I've modified my database tables to reflect the design you've described. You have a difference between your EntityFramework code-first implementation and your database. It looks like your database existed first, and I would remove your EntityFramework classes and rebuild them with Database First techniques.

Resources