I'm very new to Entity Framework, so I apologize if this is a stupid question...
Here is my POCO:
[Table("RegistrationCodes")]
public class RegistrationCode
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public Guid Code { get; set; }
public int? UserId { get; set; }
[ForeignKey("UserId")]
public UserProfile User { get; set; }
[StringLength(500)]
public string Notes { get; set; }
}
When I retrieve the object from my DBSet with the code below, UserId is always null.
return this.Context.RegistrationCodes.FirstOrDefault(c => c.Code == code);
I've checked the database and verified that the UserId is not null. Additionally, i have profiled and can see that the UserId is being requested from the database.
Any help would be greatly appreciated.
Ohhhhh my, don't I feel stupid...
Here's what was happening, I run the code and I can see the UserId field is updated in the database. Every time I restart the application, code migrations would run add do an AddOrUpdate to the table which would null out the UserId column.
Can we just delete this question all together?
Related
We have a DTO - Employee - with many (> 20) related DTOs and DTO collections. For "size of returned JSON" reasons, we have marked those relationships as [Ignore]. It is then up to the client to populate any related DTOs that they would like using other REST calls.
We have tried a couple of things to satisfy clients' desire to have some related Employee info but not all:
We created a new DTO - EmployeeLite - which has the most-requested fields defined with "RelatedTableNameRelatedFieldName" approach and used the QueryBase overload and that has worked well.
We've also tried adding a property to a request DTO - "References" - which is a comma-separated list of related DTOs that the client would like populated. We then iterate the response and populate each Employee with the related DTO or List. The concern there is performance when iterating a large List.
We're wondering if there a suggested approach to what we're trying to do?
Thanks for any suggestions you may have.
UPDATE:
Here is a portion of our request DTO:
[Route("/employees", "GET")]
public class FindEmployeesRequest : QueryDb<Employee> {
public int? ID { get; set; }
public int[] IDs { get; set; }
public string UserID { get; set; }
public string LastNameStartsWith { get; set; }
public DateTime[] DateOfBirthBetween { get; set; }
public DateTime[] HireDateBetween { get; set; }
public bool? IsActive { get; set; }
}
There is no code for the service (automagical with QueryDb), so I added some to try the "merge" approach:
public object Get(FindEmployeesRequest request) {
var query = AutoQuery.CreateQuery(request, Request.GetRequestParams());
QueryResponse<Employee> response = AutoQuery.Execute(request, query);
if (response.Total > 0) {
List<Clerkship> clerkships = Db.Select<Clerkship>();
response.Results.Merge(clerkships);
}
return response;
}
This fails with Could not find Child Reference for 'Clerkship' on Parent 'Employee'
because in Employee we have:
[Ignore]
public List<Clerkship> Clerkships { get; set; }
which we did because we don't want "Clerkships" with every request. If I change [Ignore] to [Reference] I don't need the code above in the service - the List comes automatically. So it seems that .Merge only works with [Reference] which we don't want to do.
I'm not sure how I would use the "Custom Load References" approach in an AutoQuery service. And, AFAIKT, the "Custom Fields" approach can't be use for related DTOs, only for fields in the base table.
UPDATE 2:
The LoadSelect with include[] is working well for us. We are now trying to cover the case where ?fields= is used in the query string but the client does not request the ID field of the related DTO:
public partial class Employee {
[PrimaryKey]
[AutoIncrement]
public int ID { get; set; }
.
.
.
[References(typeof(Department))]
public int DepartmentID { get; set; }
.
.
.
public class Department {
[PrimaryKey]
public int ID { get; set; }
public string Name { get; set; }
.
.
.
}
So, for the request
/employees?fields=id,departmentid
we will get the Department in the response. But for the request
/employees?fields=id
we won't get the Department in the response.
We're trying to "quietly fix" this for the requester by modifying the query.SelectExpression and adding , "Employee"."DepartmentID" to the SELECT before doing the Db.LoadSelect. Debugging shows that query.SelectExpression is being modified, but according to SQL Profiler, "Employee"."DepartmentID" is not being selected.
Is there something else we should be doing to get "Employee"."DepartmentID" added to the SELECT?
Thanks.
UPDATE 3:
The Employee table has three 1:1 relationships - EmployeeType, Department and Title:
public partial class Employee {
[PrimaryKey]
[AutoIncrement]
public int ID { get; set; }
[References(typeof(EmployeeType))]
public int EmployeeTypeID { get; set; }
[References(typeof(Department))]
public int DepartmentID { get; set; }
[References(typeof(Title))]
public int TitleID { get; set; }
.
.
.
}
public class EmployeeType {
[PrimaryKey]
public int ID { get; set; }
public string Name { get; set; }
}
public class Department {
[PrimaryKey]
public int ID { get; set; }
public string Name { get; set; }
[Reference]
public List<Title> Titles { get; set; }
}
public class Title {
[PrimaryKey]
public int ID { get; set; }
[References(typeof(Department))]
public int DepartmentID { get; set; }
public string Name { get; set; }
}
The latest update to 4.0.55 allows this:
/employees?fields=employeetype,department,title
I get back all the Employee table fields plus the three related DTOs - with one strange thing - the Employee's ID field is populated with the Employee's TitleID values (I think we saw this before?).
This request fixes that anomaly:
/employees?fields=id,employeetypeid,employeetype,departmentid,department,titleid,title
but I lose all of the other Employee fields.
This sounds like a "have your cake and eat it too" request, but is there a way that I can get all of the Employee fields and selective related DTOs? Something like:
/employees?fields=*,employeetype,department,title
AutoQuery Customizable Fields
Not sure if this is Relevant but AutoQuery has built-in support for Customizing which fields to return with the ?fields=Field1,Field2 option.
Merge disconnected POCO Results
As you've not provided any source code it's not clear what you're trying to achieve or where the inefficiency with the existing solution lies, but you don't want to be doing any N+1 SELECT queries. If you are, have a look at how you can merge disconnected POCO results together which will let you merge results from separate queries based on the relationships defined using OrmLite references, e.g the example below uses 2 distinct queries to join Customers with their orders:
//Select Customers who've had orders with Quantities of 10 or more
List<Customer> customers = db.Select<Customer>(q =>
q.Join<Order>()
.Where<Order>(o => o.Qty >= 10)
.SelectDistinct());
//Select Orders with Quantities of 10 or more
List<Order> orders = db.Select<Order>(o => o.Qty >= 10);
customers.Merge(orders); // Merge disconnected Orders with their related Customers
Custom Load References
You can selectively control which references OrmLite should load by specifying them when you call OrmLite's Load* API's, e.g:
var customerWithAddress = db.LoadSingleById<Customer>(customer.Id,
include: new[] { "PrimaryAddress" });
Using Custom Load References in AutoQuery
You can customize an AutoQuery Request to not return any references by using Db.Select instead of Db.LoadSelect in your custom AutoQuery implementation, e.g:
public object Get(FindEmployeesRequest request)
{
var q = AutoQuery.CreateQuery(request, Request);
var response = new QueryResponse<Employee>
{
Offset = q.Offset.GetValueOrDefault(0),
Results = Db.Select(q),
Total = (int)Db.Count(q),
};
return response;
}
Likewise if you only want to selectively load 1 or more references you can change LoadSelect to pass in an include: array with only the reference fields you want included, e.g:
public object Get(FindEmployeesRequest request)
{
var q = AutoQuery.CreateQuery(request, Request);
var response = new QueryResponse<Employee>
{
Offset = q.Offset.GetValueOrDefault(0),
Results = Db.LoadSelect(q, include:new []{ "Clerkships" }),
Total = (int)Db.Count(q),
};
return response;
}
I am getting an Object reference not set to an instance of an object error when trying to add multiple entity levels to my EF context.
Take the following three-level example class structure:
public class Forum
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Blog> Blogs { get; set; }
}
public class Blog
{
public int ID { get; set; }
public string Name { get; set; }
public int ForumID { get; set; }
public virtual Forum Forum { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public class Post
{
public int ID { get; set; }
public string Name { get; set; }
public int BlogID { get; set; }
public virtual Blog Blog { get; set; }
}
For a given Forum, I want to add a new Blog with a new Post:
Forum MyForum = context.Forums.Find(1);
Blog MyBlog = new Blog { Name = "My New Blog" };
Post MyPost = new Post { Name = "My New Post" };
MyForum.Blogs.Add(MyBlog); // This WORKS
MyBlog.Posts.Add(MyPost); // This FAILS
context.SaveChanges(); // We never make it this far
I've tried every possible order combination, including placing context.SaveChanges() immediately after .Add(MyBlog). It seems like it's choking because there is no Blog.ID to use for Post.BlogID, but EF generates temporary key values for use in this situation.
Any ideas?
Hints at the answer (and the root problem) can be found at:
Entity Framework Uninitialised Collection
Entity Framework 4.1 Code First - Should many relationship ICollections be initialised
The "simple" solution is to manually initialize the Blog.Posts collection:
Blog MyBlog = new Blog { Name = "My New Post", Posts = new List<Post>() };
Alternatively, you can build this logic into the class constructor as recommended by Ladislav in the second link.
Basically, when you create a new object, the collection is null and not initialized as a List<>, so the .Add() call fails. The Forum.Blogs collection is able to lazy-load because it derives from the database context. Blog.Posts, however, is created from scratch, and EF can't help you, so the collection is null by default.
I am facing an issue while inserting an entity. I am not sure what is wrong in there.
As I insert, I get an StorageClientException stating "value out of range".
My Table Service Entity looks like
public class Itinerary : TableServiceEntity
{
public string Name { get; set; }
public DateTime DOB { get; set; }
public int Sex { get; set; }
public string ToPNR { get; set; }
public string ReturnPNR { get; set; }
public string ContactNumber { get; set; }
public DateTime TravelDate { get; set; }
public DateTime ReturnDate { get; set; }
}
The entity gets inserted when the complete itinerary details are provided, but for itinerary having only one side details, the insert method gets failed with the given exception.
Any help would be appreciated.
The problem I guess lies with your DateTime fields. If you haven't initialized them before storing your data in the Table Storage, then the values that will be assigned to these fields will be that of .NET DateTime.Min value. Unfortunately this value is out of bounds of Azure Table Storage. Hence it is always advisable to provide some value to your DateTime field in the Azure Table Storage. In case, you want to assign a default value to the same, use the CloudTableClient.MinSupportedDateTime property. This will initialize the field with the min value supported by Azure Storage -
http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudtableclient.minsupporteddatetime.aspx
Hope this helps
My project is the throwing the above error because the Ship Date in my table is null. I am using Code First, and the DateTime field is declared as nullable both in the generic set and the SQL table. I am populating a gridview with the result set. Ideally, I would like to have the gridview display "not yet shipped" when the ShipDate field is null, but at this point, I would be happy just to be able to display the record. Any help is greatly appreciated. Here is the code-behind and the context class that I am using:
public class Order
{
[Key]
public int OrderID { get; set; }
public int CustomerID { get; set; }
public string ShipAddress { get; set; }
public string ShipCity { get; set; }
public string ShipState { get; set; }
public string ShipZip { get; set; }
[ScaffoldColumn(false)]
public string PaymentTransactionID { get; set; }
[ScaffoldColumn(false)]
public System.DateTime OrderDate { get; set; }
public System.DateTime? ShipDate { get; set; }
public virtual Customers Customers { get; set; }
public List<OrderDetail> OrderDetails { get; set; }
}
The code behind is:
public List<OrderDetail> FetchByOrderID()
{
int myOrderID = CusOrderId;
ProductContext db = new ProductContext();
return db.OrderDetails.Where(
c => c.OrderID == myOrderID).ToList();
}
I was getting the above error when trying to get the max(date_column) through LINQ. The column was defined as NOT NULL and when there are no rows returned in the query its trying to assign null to the DateTime property that's representing the date column. One solution is to change the date column to being NULLable which will create the entities property as type DateTime?
I use VB.Net, but had a similar problem. I do not know if you fixed your problem.
But I declared the variable as Nullable(Of Date) and that did the trick to me. I am told that adding the "?" does the similar thing, but unfortunately did not work out for me, or I did not do it correctly. :o)
private DateTime? _settlementDate {get;set;}
I was having a similar problem, same error.
Turns out I failed to setup my ConnectionString in the configuration.
There seems to be hardly any examples out there so here goes:
Here are my three structures but it doesn't seem to create the tables properly and when I call the following line it says Id is not recognised:
IEnumerable<Permission> permissions = _data.Find<RolePermission>(x => x.Role.RoleKey == roleKey).Select(x => x.Permission);
RolePermission:
public class RolePermission
{
[SubSonicPrimaryKey]
public int RolePermissionId { get; set; }
public int RoleId { get; set; }
public int PermissionId { get; set; }
//Foreign Key of Role
public Role Role { get; set; }
//Foreign key of Permission
public Permission Permission { get; set; }
}
Permission:
public class Permission
{
[SubSonicPrimaryKey]
public int Id { get; set; }
[SubSonicLongString]
public string PermissionKey { get; set; }
[SubSonicLongString]
public string PermissionDescription { get; set; }
}
Role:
public class Role
{
[SubSonicPrimaryKey]
public int Id { get; set; }
[SubSonicLongString]
public string RoleKey { get; set; }
[SubSonicLongString]
public string RoleDescription { get; set; }
}
I don't know if this has been fixed in a current release but I remember a silly bug in subsonic's primary key detection.
If your Object contains a property named Id subsonic assumes that is your primary key.
If not you have to tell subsonic with is your PK by decorating a property with the SubSonicPrimaryKey attribute (like you did).
If you have a property called Id and it is also decorated with the attribute (like your Role and Permission class) subsonic finds the property twice and does not check if they both equals. Then it throws an exception because it can't reliably determine which one to take.
Long story short, you should try:
a) Remove the Attribute from your Id column
b) Rename the property to RoleId or PermissionId (which would be more consistend because your RolePermission class has it's PK called RolePermissionId)
If that doesn't help, please provide a stacktrace.