How to write null to Guid? field in DB? - sql

I have a guid? field in my POCO and when I create a new entry in my DB and look at it through SSMSE, I see NULL in that field. After choosing a manager for this new user entry, the guid? field is updated to hold the id of the new manager. However, if I want to change the user back to having no manager, how can I set the field back to NULL?
Should I be using Guid instead of Guid? and write Guid.Empty to the DB instead?

Should I be using Guid instead of Guid? and write Guid.Empty to the DB instead?
Not really. You could do that, but you wouldn't really gain much. Semantically, if there is "no" value for a field, NULL is the correct value. What you are talking about is using a magic value.
how can I set the field back to NULL?
Set the Guid? to null on your POCO. For example, if your POCO looks something like this:
public class Poco
{
public Guid? Manager { get; set; }
}
Set it to null like this:
somepocoinstance.Manager = null;
Then commit the changes.

Related

Problem With Inserting Record And Assigning Primary Key EF Core 3.0

I have a simple model record with a key "Id" that I'm adding to a EF Entity. It worked through Core 2.1 but now fails with the error:
SqlException: Cannot insert explicit value for identity column in table 'SpeakerRecs' when IDENTITY_INSERT is set to OFF.
The Model is defined as follows:
namespace WebAppCore.Models
{
public class SpeakerRec
{
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string ImageUrl { get; set; }
}
}
The Code that does the insert is this and it fails on the save changes call.
foreach (var speaker in speakerRecs)
{
_context.SpeakerRecs.Add(speaker);
}
_context.SaveChanges();
I see notes about breaking changes in Core 3 and the problem is somehow around ValueGeneratedNever() but can't figure it out. I've not used EF for a while and was not planning on re-learning it. I was hoping my old code would continue to work.
If you want to manually insert the Id , you can use [DatabaseGenerated(DatabaseGeneratedOption.None)] . The None option prevents values from being generated by the database automatically in cases where they would otherwise be created :
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
If you have created the migration before , when create new migration and update database , you may get exception like To change the IDENTITY property of a column, the column needs to be dropped and recreated , you can :
Delete the actual database
Delete the Migrations folder in your project and clean the project
Create a new migration with dd-migration <migration_name> in the Package Manager Console and then Update-database .
You are inserting explicit values in the Id column, which is an identity column. To insert value explicitly into the identity column you have to turn on the identity insert.
If your database is automatically inserting value for the Id column, you should not specify them externally from your code.
Update your edmx file to reflect any changes you may have made in the database. If the database automatically assigns the value, you should see the "IsDbGenerated=true" attribute in your designer file under that property. If it's not there, you can add it manually.
Reference

EF Core: conditionally computed column

In my model I have AccountType property, which is mostly generated by database trigger, but sometimes can also be directly assigned:
public class Account
{
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public int AccountType { get; set; }
}
The attribute [DatabaseGenerated] allows me to automatically get database generated value back, whenever databaseContext.SaveChanges() executed.
However, this attribute seems to also prevent sending a value, if
I wish to assign AccountType explicitly. What is the best way to implement such "partially" generated/computed column?
However, this attribute seems to also prevent sending a value, if I wish to assign AccountType explicitly. What is the best way to implement such "partially" generated/computed column?
If you want to set a explicit value to a property decorected with [DatabaseGenerated(DatabaseGeneratedOption.Computed)] , you need to drop down to the lower level metadata API and set AfterSaveBehavior/BeforeSaveBehavior like below :
IMutableProperty.BeforeSaveBehavior Property is used for Add state
modelBuilder.Entity<Test>()
.Property(t => t.TestType)
.Metadata.BeforeSaveBehavior=PropertySaveBehavior.Save;
IMutableProperty.AfterSaveBehavior Property is used for Update state
modelBuilder.Entity<Test>()
.Property(t => t.TestType)
.Metadata.AfterSaveBehavior =PropertySaveBehavior.Save;
The PropertySaveBehavior indicates how changes to the value of a property will be handled by Entity Framework change tracking which in turn will determine whether the value set is sent to the database or not.

MVC4 Code First Database type "Date"

I need a database column to be a date data type in a MS SQL Server. It's a requirement for the project, it cannot be datetime.
In my model I have:
[DataType(DataType.Date)]
public DateTime? RequestedCompletionDate { get; set; }
This still creates the column as a nullable datetime. Is there any way to make it date code first?
After a lot of research I finally figured out how to do it.
In my model rather than using the DataType attribute I used the column attribute. My model now looks like this:
[Column(TypeName="date")]
public DateTime? RequestedCompletionDate { get; set; }
If anyone is trying to do something similar, although I used TypeName="date", you should be able to set TypeName to anything you want as long as it is a valid SQL Server Data Type.

Changing the value of an Id in RavenDB

We have an entity named Organization that we use the UniqueConstraints-bundle on. We have a property named NetName that is a UniqueConstraint and an automaticly generated Id.
Since this is unneccesary we want to use the NetName-property as Id instead. So that we don't need UniqueConstraints to know that it is unique and also get the benefit from being able to use Load when we have the NetName.
We needed to clean up our netname a bit before using it as an Id so we created a new temporary-property called TempUniqueNetName that now holds the value of:
"organizations/"+ CleanupId(this.NetName)
So we are now ready to simply move that value to our Id. But we can't get it to work. Our problem is that with the PatchRequest below we end up with a new property named Id in the database but the acctual Id still has the same value (see screenshot). Is there a better (correct) way to change the value of an Id?
The Entity:
class Organization {
public string Id { get; set; }
[UniqueConstraint]
public string NetName { get; set; }
public string TempUniqueNetName{ get; set; }
}
We want to do something like this:
_documentStore.DatabaseCommands.UpdateByIndex(typeof(Organizations).Name,
new IndexQuery(),
new[]
{
new PatchRequest()
{
Type = PatchCommandType.Rename,
Name = "TempUniqueNetName",
Value = new RavenJValue("Id")
}
});
I don't think you can change the document key via patching. It's not actually stored with the document or the metadata - it's copied into the #id metadata on load to give you the illusion that it's there, and the Raven Client copies it again into your own identity property in the document. But really, it's a separate value in the underlying esent document store. Raven would have to know specifically how to handle this and fake it for you.
You could manually copy the doc from the old id to the new one and delete the old, but that could be time consuming.
There isn't a great answer for renaming a document key right now. There really should be a DatabaseCommand for rekeying a single document, and separate PatchCommandType to rekey when patching. Perhaps this will be added to raven in the future.
You can check implemtation of PUT-DELETE usage for updating IDs in my github repo.
It should look something like this:
store.DatabaseCommands.Put(updatedKey, null, document.DataAsJson, newMetadata);
store.DatabaseCommands.Delete(oldKey, null);
https://github.com/Sevsoad/SagaUpdater/
Also here is some Raven documentation:
https://ravendb.net/docs/article-page/3.0/csharp/client-api/commands/documents/put

Fluent-NHibernate and persisting DateTime automatically

I'm using S#arpArchitecture (ASP.NET MVC and Fluent NHibernate). I have an entity as follows:
public class User : Entity
{
public User(){}
public User(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual DateTime? LastUpdate{ get; set; }
}
I will call the SaveOrUpdate method on my repository class that will persist this User object. It works. How would i persist the LastUpdate property automatically with the latest date and time? I could override the SaveOrUpdate method in my repository by always setting the LastUpdate property to the current date and time but that does not seem to be correct because if there's nothing changed in my entity, I don't think NHibernate will persist my object back to the DB and forcing the setting of this property will always make it persist back.
I only want this LastUpdate property set if something else has changed in my entity.
You should use an NHibernate Interceptor to accomplish this. Override OnFlushDirty in your interceptor implementation to set the LastUpdate property only when something has changed (i.e. your object is dirty).
Since you didn't specify your database type, I will take the liberty and add a solution for people using MySQL / MariaDB:
You can use the following in your fluent mapping class:
Map(y => y.LastUpdate).CustomSqlType("timestamp").Generated.Always();
This creates a MySQL TIMESTAMP column with a default value of CURRENT_TIMESTAMP. Thus, if Nhibernate chooses to flush your entity, MySQL will make sure that the column is properly updated.
I'm pretty sure this does not play well with MSSQL as TIMESTAMPS are different beasts in MSSQL (here and here)
I'm going to point to another StackOverflow question that I think answers my question.