Entity Framework: Add-Migration is removing the nullable:false (allowing null) - entity-framework

The migration believes email should now be nullable, and I can't see where it's coming up with this idea. The database before the migration is NOT NULL. Running Add-Migration produces the code changes below, where Email is now marked nullable; however, the [Required] attribute is present on the string and this code has been untouched for sometime. What are some other side-effects that could be causing this behavior? (Target is SQL server)
(1) Unchanged Model:
[Table("UserProfile")]
public class UserProfile
{
// .. snip...
[JsonProperty("email"), Required, Display(Name = "Email")]
public string Email { get; set; }
}
(2)
Add-Migration ExampleMigration
(3) Output migration:
public partial class ExampleMigration : DbMigration
{
public override void Up()
{
AlterColumn("dbo.UserProfile", "Email", c => c.String());
}
public override void Down()
{
AlterColumn("dbo.UserProfile", "Email", c => c.String(nullable: false));
}
}
Comparing resx migration schemas shows the same result, where the latest migration removes Nullable="false".
Before
<Property Name="Email" Type="String" MaxLength="Max" FixedLength="false" Unicode="true" Nullable="false" />
After
<Property Name="Email" Type="String" MaxLength="Max" FixedLength="false" Unicode="true" />

To work around this issue, I ran the migration, removed the incorrect lines from up/down, did a file compare against the prior and current migration decompressed 'target' value in the resx, took the changes I wanted, and recompressed the result and jammed it back in the resx.
Not ideal. Not recommended.

Related

Conflict "add-migration" and "update-database" result for entity framework code base migration

I tried to run code base entity framework migration. And I always get this error (except the initial migration) when run "add-migration" command: Unable to generate an explicit migration because the following explicit migrations are pending: [201607141552034_Add_storeId_firstname_to_customer]. Apply the pending explicit migrations before attempting to generate a new explicit migration. However, if I try to run "update-database -Verbose -ConnectionStringName "ZzaDbConnectionString", I get an very confusing/conflict error: No pending explicit migrations. I tried to delete the migration file then use add-migration to create it again. It only work once. The next time (for example, if I want to add a column to my table), I got the same error. Any suggestion why the problem? Thanks.
EDIT: add code and configuration.
This is Entity class.
namespace Zza.Entities
{
public class Customer
{
public Guid Id { get; set; }
[MaxLength(50)]
public string FullName { get; set; }
}
}
This is Context class:
namespace Zza.Data
{
public class ZzaDbContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
}
}
This is console class:
namespace TestEFMigration
{
public class Program
{
static void Main(string[] args)
{
CreateDataBase();
}
private static void CreateDataBase()
{
var context = new ZzaDbContext();
context.Database.Initialize(false);
}
}
}
context class's app.config
<add name="ZzaDbConnectionString"
connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Zza;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite‌​;MultiSubnetFailover=False"
providerName="System.Data.SqlClient" />
Console's app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<connectionStrings>
<add name="ZzaDbConnectionString" connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Zza;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
iceheart

Entity Framework code first, change maxlength only, does not trigger model change

When I change my model attribute from this
[Column(TypeName = "nvarchar"), MaxLength(8)]
to this
[Column(TypeName = "nvarchar"), MaxLength(32)]
I get NO model change:
public partial class V0114 : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
Is there a workaround for this?
We use this version: <package id="EntityFramework" version="6.1.3" targetFramework="net451" />
Ps the rest works; if I add a new property on the class all goes well and with all previous changes (in which we all had largere changes) we encountered no problems.
Ps2 it's a bugfix, so after a few hours I also 'dirty' workarounds are welcome

Object of type 'System.String' cannot be converted to type 'MongoDB.Bson.ObjectId'

I have a C# class which has an id field of type ObjectId:
[BsonId]
[SolrUniqueKey("id")]
public ObjectId Id { get; set; }
In Solr, the schema has defined id as:
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
When attempting to pull an object from Solr it fails because it can't cast the string id to MongoDB ObjectId. Does anyone an easy was of fixing this without changing the source for SolrNet?
For anyone interested, below is how I ended-up doing it without modifying SolrNet source code.
I've added an additional property in the class called IdAsString and set it as "BsonIgnore" so that it doesn't get stored in MongoDB, however I use that field to map it to Solr's id field:
[BsonId]
public ObjectId Id { get; set; }
[BsonIgnore]
[SolrUniqueKey("id")]
public string IdAsString
{
get { return Id.ToString(); }
set { Id = ObjectId.Parse(value); }
}

odata breeze: Collection of ComplexType: - "TypeError: Cannot call method '_createInstanceCore…"

I would like to use Breeze to work with an OData Service. I spent hours trying to get this running, but I did not find a solution, so I really hope anybody can help!? (I just started to use breeze - so I am sorry if I am missing something "obvious" here.)
What I would like to do is to use a Collection of sub-objects (ComplexType). I.e. I would like my entity class to have a collection property like this:
public List<Address> addresses { get; set; }
(Address is no entity which is persisted on its own in a DB collection, but a simple class with some properties (ComplexType))
The server is a MVC4 WebAPI ODATA Service that is based on Entity Framework Code First POCO classes that are persisted in a MongoDB database.
In the browser I get the following error, when the breeze library tries to read the ODATA metadata from the server (it does not even query the example collection, it has an error before that):
[Q] Unhandled rejection reasons (should be empty):
["TypeError: Cannot call method '_createInstanceCore…://localhost:56936/scripts/breeze.debug.js:236:26"]
Is there any way to get this running?
Thank you!
My client code looks like this:
var serverAddress = "http://localhost:56936/odata";
breeze.config.initializeAdapterInstances({ dataService: "OData" });
var manager = new breeze.EntityManager(serverAddress);
var query = breeze.EntityQuery.from("BreezeExample");
manager.executeQuery(query).then(querysucceeded).fail(queryfailed);
function querysucceeded(data) {
console.log("querysucceeded");
data.results.forEach(function (item) {
//...
});
}
function queryfailed(e) {
console.log("!!! queryfailed");
console.log(e);
}
The Model is as follows:
[BsonIgnoreExtraElements]
public class ExampleClass : MongoEntity
{
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string loginEmail { get; set; }
public bool? active { get; set; }
public ICollection<Address> addresses { get; set; } //THIS DOES NOT WORK CLIENT SIDE - WHY?
}
public class Address
{
public string place { get; set; }
public string street { get; set; }
public string houseNumber { get; set; }
public string postalCode { get; set; }
}
If I query the ODATA metadata using the browser (http://localhost:56936/odata/$metadata), I get this result:
<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" Version="1.0">
<edmx:DataServices xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="3.0" m:MaxDataServiceVersion="3.0">
<Schema xmlns="http://schemas.microsoft.com/ado/2009/11/edm" Namespace="MvcWebRole1.Models.MongoDB.Entities">
<EntityType Name="ExampleClass">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="loginEmail" Type="Edm.String" />
<Property Name="active" Type="Edm.Boolean" />
<Property Name="addresses" Type="Collection(MvcWebRole1.Models.MongoDB.Entities.Address)" Nullable="false" />
<Property Name="Id" Type="Edm.String" Nullable="false" />
</EntityType>
<ComplexType Name="Address">
<Property Name="place" Type="Edm.String" />
<Property Name="street" Type="Edm.String" />
<Property Name="houseNumber" Type="Edm.String" />
<Property Name="postalCode" Type="Edm.String" />
</ComplexType>
<EntityContainer Name="Container" m:IsDefaultEntityContainer="true">
<EntitySet Name="BreezeExample" EntityType="MvcWebRole1.Models.MongoDB.Entities.ExampleClass" />
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
If I query the BreezeExample collection (http://localhost:56936/odata/BreezeExample) I get this:
{
odata.metadata: "http://localhost:56936/odata/$metadata#BreezeExample",
value: [
{
loginEmail: "loginEmail1",
active: true,
addresses: [
{
place: "place",
street: "street",
houseNumber: "77",
postalCode: "123"
},
{
place: "place2",
street: "street",
houseNumber: "77",
postalCode: "123"
}
],
Id: "1"
},
{
loginEmail: "loginEmail2",
active: true,
addresses: [
{
place: "place",
street: "street",
houseNumber: "77",
postalCode: "123"
},
{
place: "place",
street: "street",
houseNumber: "77",
postalCode: "123"
}
],
Id: "2"
}
]
}
I managed to partially fix the problem by doing the following:
First of all, it turns out that Breeze doesn't understand the Collection(MvcWebRole1.Models.MongoDB.Entities.Address) type; So it cannot create the appropriate dataType property. This might be the reason while you get the error.
I changed the type to something like Edm.Self.Address.
The other change that I made was in the parseCsdlComplexProperty function. I added one more line which fixed everything.
var dp = new DataProperty({
nameOnServer: csdlProperty.name,
complexTypeName: complexTypeName,
isScalar: csdlProperty.isScalar, // LINE ADDED
isNullable: false
});
Just to recap, my metada file contains the following snippet
{
"name": "ColourByType",
"key": {
"propertyRef": {
"name": "Id"
}
},
"property": [
{
"name": "Id",
"type": "Edm.Int32",
"nullable": "false",
"annotation:StoreGeneratedPattern": "Identity"
},
{
"name": "Options", // This is the list that holds the instance of my complex type
"type": "Edm.Self.ColourByOption", // This is the complex type that is stored in the list
"isScalar": false
}
]
}
I'm sure that this solution is not ideal, but it worked for me.
I've asked a similar question; so you might want to keep on eye on it, as well
https://stackoverflow.com/questions/21258015/breezejs-metadata-is-missing-information-about-complex-properties

Problem with data binding in xaml through a RIA Domain Service

I have an entity framework with a many-to-many relationship between Customers and Contacts.
I have generated a Domain Service Class and added the following method manually.
public Customer GetCustomerById(int Id)
{
return this.ObjectContext.Customer.Include("Contacts").SingleOrDefault(s => s.Id == Id);
}
I now want to create a page that shows me the customer details and a list of contacts associated with that customer.
I have the following in codebehind of the customerdetails.xaml to read the Id parameter that gets passed into the page.
public int CustomerId
{
get { return (int)this.GetValue(CustomerIdProperty); }
set { this.SetValue(CustomerIdProperty, value); }
}
public static DependencyProperty CustomerIdProperty = DependencyProperty.Register("CustomerId", typeof(int), typeof(CustomerDetails), new PropertyMetadata(0));
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (this.NavigationContext.QueryString.ContainsKey("Id"))
{
CustomerId = Convert.ToInt32(this.NavigationContext.QueryString["Id"]);
}
}
I use the following xaml for the page:
<Grid x:Name="LayoutRoot" DataContext="{Binding ElementName=customerByIdSource, Path=Data}">
<riaControls:DomainDataSource Name="customerByIdSource" AutoLoad="True" QueryName="GetCustomerById">
<riaControls:DomainDataSource.QueryParameters>
<riaControls:Parameter ParameterName="Id" Value="{Binding ElementName=CustomerDetailsPage, Path=CustomerId}" />
</riaControls:DomainDataSource.QueryParameters>
<riaControls:DomainDataSource.DomainContext>
<sprint:Customer2DomainContext/>
</riaControls:DomainDataSource.DomainContext>
</riaControls:DomainDataSource>
<StackPanel x:Name="CustomerInfo" Orientation="Vertical">
<StackPanel Orientation="Horizontal" Margin="3,3,3,3">
<TextBlock Text="Id"/>
<TextBox x:Name="idTextBox" Text="{Binding Id}" Width="160"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="3,3,3,3">
<TextBlock Text="Name"/>
<TextBox x:Name="nameTextBox" Text="{Binding Name}" Width="160"/>
</StackPanel>
<ListBox ItemsSource="{Binding Contact}" DisplayMemberPath="FullName" Height="100" />
</StackPanel>
</Grid>
When I do this the textboxes get nicely populated through the databinding, but the listbox remains empty.
Two questions:
Can I somehow specify the return
type of the GetCustomerById query,
so I can see the names when I
specify the binding through the
properties GUI?
What am I doing
wrong here? Why isn't my ListBox
populated? Am I going about this the correct way or do I need to set the databinding for the listbox in codebehind as well? If so, how? I haven't found how toaccess the Contacts property via the domain data source programmatically.
I use silverlight and entity framework 4.
I have found an answer to my question 2:
The association property Contacts is not included in the Domain Service Object types that are generated. You have to specify the [Include] attribute for them to be included. However the include attribute requires an [Association] attribute. You can not specify the [Association] attribute because this is a many to many relationship and the association attribute requires you to specify foreign keys.
The solution is to wrap your objects in a data transfer object (DTO). I did not have to make major changes to the code that was already in my question. The only thing changed was the retrieval of the Customer in the domain service class:
public CustomerDTO GetCustomerById(int Id)
{
return new CustomerDTO(this.ObjectContext.Customers.Include("Contacts").SingleOrDefault(s => s.Id == Id));
}
The main part of the solution was to change add the DTO classes to the underlying entity framework model:
[DataContract]
public partial class CustomerDTO : Customer
{
public CustomerDTO() { }
public CustomerDTO(Customer customer)
{
if (customer != null)
{
Id = customer.Id;
Name = customer.Name;
CustomerContacts = new Collection<ContactDTO>();
foreach (Contact d in customer.Contacts)
{
CustomerContacts.Add(new ContactDTO(d, Id));
}
}
}
[DataMember]
[Include]
[Association("CustomerContacts", "CustomerId", "Id")]
public Collection<ContactDTO> CustomerContacts
{
get;
set;
}
}
[KnownType(typeof(CustomerDTO))]
public partial class Customer
{
}
[DataContract()]
public partial class ContactDTO : Contact
{
public ContactDTO() { }
public ContactDTO(Contact contact, int customerId)
{
if (contact != null)
{
Id = contact.Id;
FullName = contact.FullName;
CustomerId = customerId;
}
}
[DataMember]
public int CustomerId { get; set; }
}
[KnownType(typeof(ContactDTO))]
public partial class Contact
{
}
The KnownType, DataMember and DataContract attributes were required to get this to work. In reality instantiating the objects will require a bit more copying of properties in the constructors. Is there an easy way to avoid code that does an explicit copy? I'm open for suggestions.
I was hoping to avoid the introduction of extra classes, but it seems unavoidable in case of a many to many relationship, because of the required Association attribute that needs a foreign key specification; in my case Contact.CustomerId.
Can anybody do better (== less coding) ?