I have an existing database, and if I define a new bool hide_in_main_screen = false; property in my objectbox class, and I query it like Store.box<TM>().query(TM_.hide_in_main_screen.equals(false)).build().find(), I got 0 items.
If I query the whole table I see that this property value is false.
Why I don't get the items, and how can I solve this problem?
Based on this objectbox issue information, I created a db migration routine and filled the new properties with default values.
Related
This is EF Core 3.1. I have several models with a boolean field, IsActive, defined like so:
public class Job
{
public bool? IsActive { get; set; }
}
My seed data looks like this:
modelBuilder.Entity<Job>()
.Property(e => e.IsActive)
.HasDefaultValue(true);
modelBuilder.Entity<Job>().HasData(
new Job() { IsActive = true });
Every time I create a migration (including if I run a migration with no changes made, which should generate an empty migration), it has a UpdateData call for the field above, like so:
migrationBuilder.UpdateData(
table: "Jobs",
keyColumn: "id",
keyValue: 1L,
column: "IsActive",
value: true);
I've also replicated this behavior in the TodoApi app and setup a GitHub repo for anyone interested in more details.
I understand that happening when the seed data is being generated by a function, or the result of something like DateTime.Now. I don't understand it happening here, when the column is assigned a raw boolean value during seeding.
This behavior seems very similar to issue #13047, "Incorrect UpdateData operations generated when using BoolToStringConverter with HasData", but that issue was fixed in EF Core 2.2.
Well the reason is the HasDefaultValue(true) call in the following model configuration code -
modelBuilder.Entity<Job>()
.Property(e => e.IsActive)
.HasDefaultValue(true);
Whenever you set a default value for a property with the HasDefaultValue() method, that is the value to be set for the respective column in the database table.
With HasDefaultValue(true), you have set true to be the default value for IsActive property. Therefore, in the seed data -
modelBuilder.Entity<Job>().HasData(
new Job() { IsActive = true });
setting a value to IsActive (doesn't matter whatever the value is) is a change from migration's perspective, even though the data didn't change between migrations.
EDIT - What is the solution:
The requirement to set default value for a column is always a valid requirement. So the other thing you might consider to change is the data seeding approach.
The seeding approach you are using now is completely managed by migrations itself, and it has some limitations - Limitations of model seed data
You can use a Custom initialization logic to seed data which migrations has nothing to do with.
I've been trying to update an Entity using the following code:
var db = new MyContext();
var data = db.Tableau.Find(Id);
if (data != null)
{
data.Name = model.Name;
data.EmbedCode = model.EmbedCode;
db.SaveChanges();
}
The problem is that my Tableaus table has a Parent field (FK not null to a DataTree table). Sometimes when I save the changes to this edited record, I get an error saying that "The Parent field is required". But I am not editing the Parent field. The parent field should be intact and existent, since I am only altering the Name and EmbedCode fields.
How to proceed? Thanks in advance.
That is because you are allowing null values in ParentId column in your Tableaus table, but in your Tableau entity you have ParentId as non-nullable property( which it means the relationship is required), and when you load a Tableau instance from your DB, EF expects that you set that property too. Try changing that property to nullable:
public int? ParentId {get;set;}
If you configure your relationship using Fluent Api it would be:
modelBuilder.Entity<Tableau>()
.HasOptional(t=>t.Parent)
.WithMany(dt=>dt.Tablous)// if you don't have a collection nav. property in your DataTree entity, you can call this method without parameter
.HasForeignKey(t=>t.ParentId);
Update 1
If you want ParentId property as Required in your Tableau entity, you need to make sure that you have a valid value in that column in your DB per each row. With a "valid value" I mean it should be different of the default value and it should exist as PK in your DataTree table.
Update 2:
One way to load a related entity as part of your query is using Include extension method:
var data = db.Tableau.Include(t=>t.Parent).FirstOrDefault(t=>t.Id==Id);
I have a WebForms applicaiton using the new ASP.NET Identity. I've added a couple of additional fields in the class to allow for Email and a Boolean called IsOnLine.
I use migrations, to explicititly update the tables, and can see that my new fields are there. However, whenever I try to login now i get the following error:
Additional information: The 'IsOnLine' property on 'ApplicationUser' could not be set to a 'null' value. You must set this property to a non-null value of type 'System.Boolean'.
All the exmamples on the net relate to MVC, which i'm not using yet.
How can i fix this?
A bool cannot be null so that is what is set to in the database. If you want it to be null you will need to define it as a nullable bool using the ? operator.
public class ApplicationUser : IdentityUser
{
public bool? IsOnline { get; set; }
}
To update this information in the database take a look at this article on adding email confirmation to ASP.NET Identity. In this example there is a boolean flag IsConfirmed that is updated during the registration process, which will be similar to your IsOnline flag. Here is a snippet of the relevant code to update the database.
user.IsOnline = true;
DbSet<ApplicationUser> dbSet = context.Set<ApplicationUser>();
dbSet.Attach(user);
context.Entry(user).State = EntityState.Modified;
context.SaveChanges();
I prefer to avoid null values whenever possible, to determine if a property can accept nulls values it is better to think what that information represents in the domain problem. In this case i think it not make sense to have an undetermined value for IsOnline because the user is online or offline, not middle terms apply to this fact.
To resolve this problem with the database, taking advantage that you are using Code Migration , you can use the Seed method from Configuration class and assing the value(s) to your new fields that are not nullable.
Pseudo code:
Seed()
for each user
set user IsOnline to false
How can I make my own delete method to prevent that the data really gets deleted?
I want to set a datetime field when it gets deleted instead of a normal delete.
I read about overriding the submitchanges function, but I don't get it to work
Handle SavingChanges, go through the deleted items in the context, change their state to modified, and modify the field in question.
I wrote an interface IRequiredColumns with the properties CreatedOn, ModifiedOn and DeletedOn which every entity implements. Then I created this partial class for the context:
Partial Public Class Context
Public Overrides Function SaveChanges(ByVal options As System.Data.Objects.SaveOptions) As Integer
For Each entry As ObjectStateEntry In ObjectStateManager.GetObjectStateEntries(EntityState.Added Or EntityState.Modified Or EntityState.Deleted)
If TypeOf (entry.Entity) Is IRequiredColumns Then
Dim entity As IRequiredColumns = CType(entry.Entity, IRequiredColumns)
Select Case entry.State
Case EntityState.Added
entity.CreatedOn = Now
Case EntityState.Modified
entity.ModifiedOn = Now
Case EntityState.Deleted
entry.ChangeState(EntityState.Modified)
entity.DeletedOn = Now
End Select
End If
Next
Return MyBase.SaveChanges(options)
End Function
End Class
This works great for me!
If you won't find out how to override the delete function, you can create an ON DELETE trigger for every table in database, that does not delete, but sets datetime field.
Does anyone have any recommendations for working with name/value pairs in Flex?
Context:
I want to create a Flex UI for updating a database table. I want the UI to contain the field name(read only) and current field value (which will be editable). Im using the WebService component to retrieve the field value and then asssigning it to an object with the field name hardcoded e.g.
private function resultHandler(event:ResultEvent):Object
{
var resultsObj:Object;
resultsObj = {
name:event.result.name as String,
This approach however is adding the dependency that the table structure/field names will never change. Using the object type also requries that i write my own algorithm to sort the output.
I'm not sure I understand the issue.
If you want to avoid dependency of the properties returned from the event at this point, simply use the event.result object, which is already an associative array.
As for sorting, we would need more context on what you are attempting to sort.
That's pretty simple. Don't use for each in loop. Use For-In Loop
Demo is shown below.
var dicEntry:Object = new Object();
dicEntry["Name"] = "Raj";
dicEntry["sal"] = 10000;
dicEntry["age"] = 33;
for(var key:Object in dicEntry)
{
trace("Object Key: "+key+" Object Value: +dicEntry[key]);
}
That's it.