Entity Framework Add-Migration Ignores FSharpOption properties - entity-framework

I am trying to convert a C# project into F#. The C# project uses Entity Framework as the primary means of data access.
I have the following interface in F#:
type public IFoo =
abstract member Bar : DateTime option
Which is implemented by the following C# class:
public class Foo : IFoo
{
public int Id { get; set; }
public FSharpOption<DateTime> Bar { get; set; }
}
(I'm doing the conversion one piece at a time, so the interface is already in F# but the class is still in C#.)
When I run Add-Migration, the Bar property gets ignored.
The solution I currently have is to just change the interface signature of the Bar property to Nullable<DateTime>. But I believe that would prevent me from working with the interface using "idiomatic" F#.
What other alternatives do I have? Thanks in advance.

Related

EFCore/UWP missing some tables with Add-Migration

I'm starting to use EFCore in a UWP app with SQLite. I've declared the classes that I want stored in the database. I've then declared various DbSets and the OnConfiguring override:
public class DatabaseContext : DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<Relationship> Relationships { get; set; }
public DbSet<SourceDescription> SourceDescriptions { get; set; }
public DbSet<Agent> Agents { get; set; }
public DbSet<Event> Events { get; set; }
public DbSet<Document> Documents { get; set; }
public DbSet<PlaceDescription> PlaceDescriptions { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Filename=Testing.db");
}
}
In the Package Manager Console, I then go:
Add-Migration 2017-06-23
and it creates the code to then build the database. HOWEVER, that code is missing some of the top-level tables. Some of them are there but some aren't and I can't see/figure out what is causing this. No errors are generated and I cannot find a pattern to determine why the missing tables are missing.
Further information:
There are 29 classes defined in my code. The migration code creates 24 tables.
Of the 5 "missing" classes, 4 of them are derived from Subject which, in turn, derives from Conclusion. The fifth is the Conclusion class. Since the migration code "merges" the properties from each of the derived classes, I'm not surprised that the Conclusion class doesn't have its own table as there is no direct use of it as a class.
With the exception of the Conclusion class, the other 4 classes are only referenced in the DbSet properties (as opposed to be used in properties in other classes). As noted above, the Document class is derived from another class, so it isn't derived classes that is the common factor.
It isn't that some of the classes are partial classes.
I can't spot anything about the properties in the classes that is a common factor. For example, the Person class has List a couple of times but so does the Agent class and that does appear in the migration code.
Any suggestions on what I can look for or if this is a known issue?
To clarify, the answer provided by Ivan is that EF Core sees the four classes that are derived from the Subject class and builds a table for the Subject class that includes all of the properties for those derived classes. There is then a Discriminator column added to the Subject class that indicates which derived class this is for.
http://www.learnentityframeworkcore.com/inheritance/table-per-hierarchy is a good article for explaining it.
An interesting approach to designing database tables that I hadn't come across before. I live and learn :)

Scaffolding a Read Action in MVC "No parameterless constructor defined for this object."

I'm working on a basic MVC5/EF6 application and am running into the following error when I try to scaffold a Read Action in MVC:
Error
There was an error running the selected code generator:
'No Parameterless constructor defined for this object'
It should not need it anyway because I am calling a read not a delete or an update however the model in question does have a parameterless constructor (as do the models below it).
public class Article
{
public int ArticleID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime PublishDate { get; set; }
public virtual Author Author { get; set; }
public Article()
{
}
}
My controller is below and it also has a parameterless constructor:
public ArticleController()
{
connection = System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
context = new TRNContext(connection);
}
// GET: Article
public ActionResult Index(int id)
{
return View(context.Articles.SingleOrDefault(a => a.ArticleID == id));
}
I came across this error on an ASP.NET Core MVC application due to the failure to connect to the database. I spent hours checking my models and dbContext class only to realize there was nothing wrong with them. The application was just failing to connect to the database. There were two places I had to check.
Startup.cs - the database context should be registered with the correct connection string.
Appsetting.json - the connection string should be correctly typed.
The error message was slightly misleading. There was a parameter less constructor required but it was not the model it was the datacontext that needs it.
There is also a scenario with aspnet core where the Program class isn't exposing IWebHostBuilder so that design time dbcontext creation can function properly.
I spent a few hours trying to solve this error with an aspnet core 2.2 mvc app.
Take a look at this link to understand how ef core tooling works. Re-writing my Program class to support application services solved it for me since my dbcontext didn't use a parameterless constructor.
https://learn.microsoft.com/en-us/ef/core/miscellaneous/cli/dbcontext-creation
This error may be due to the situation. You have a class and this class inherits from the DbContext class. If you are generating this instead of writing the constructor method of this class, the constructor access modifier may be protected. if you edit it public, the problem will be fixed.

MVC5 website newbie / Annotations on properties of autogenerated modell

i'm new to mvc 5, and I would like to build an asp.net application to interact with an existing database. I'm using VIsual studio 2013 and Entity Framework 6.
I've generated an ADO.net Entity Data Model from an existing database and I'm currently trying to find out the best way to make data validations, to avoid wrong inputs (let's take as example the field Email from entity Users).
The right way seems to be to use Annotations on partial classes. But i don't know how to add an annotation (on the new partial class that i created for that) if the original property declaration is on the autogenerated file.
The autogenerated class, looks like:
namespace Test.Models
{
...
public partial class Users
{
public string Email { get; set; }
}
...
}
Following the idea behind [this post] (Add data annotations to a class generated by entity framework), i'm trying to make a partial class to write the annotations there, like that:
namespace Test.Models
{
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(UsersMetaData))]
public partial class Users
{
[Someanotations]
public string Email { get; set; }
}
}
But on the partial class, i get:
1) Error on the line of "[MetadataType(typeof(UsersMetadata))]", saying that UsersMetadata could not be found, and
2) Error on the line where "public string email", saying that the property is already declared (which sounds logic for me).
How should i annotate on the new partial class the property that is declared on the autogenerated model?
It is possible to define a Regex to be used on the anotation?
Thanks for your time,
John
You're almost there. UserMetadata is actually another class that you apply the annotations to. I usually put both of these in the same file.
[MetadataType(typeof(UsersMetaData))]
public partial class Users
{
}
class UsersMetaData
{
[Someanotations]
public string Email { get; set; }
}

Using generic-based role pattern with EntityFramework 4

Maybe I haven't quite get the whole thing about models. I tought that, it was probably wrong, EF framework could map any kind of class. So I did provide classes with different interfaces, with ToString() methods and so on.
I was thinking of reusable/flexible structure of classes for some kind of public organization.
For example, there are next classes
[Serializable]
public abstract class AbstractRole
{
public String Title { get; set; }
public abstract void ExecuteRole();
public abstract Decimal GetSalary();
// ToString(...) implementations and so on
}
[Serializable]
public class Employee<T> : IComparable<Employee<T>>, IFormattable where T : AbstractRole
{
private Person person;
public T Role { get; set; }
// interfaces implementations...
}
So all I wanted is to get flexibility to change employee's role in time and not to bind to its instance (avoid inheritance).
But later I read that generics are not supported by EF.
What should I do?
In case of entity framework you must provide exact type. Base classes are supported only if whole inheritance tree is mapped as well. Interfaces and generic types are not supported at all.
That means that reusable and flexible architecture is not something which can use EF.

How do I implement Business Logic on auto generated entities in Microsoft MVC2?

I'm new to MVC and I'm trying to figure out how to implement business logic in the auto generated Entities in an MVC project.
I know that if I create my own Model class I can put [Required] and other attributes on the fields but there doesn't seem to be an option to do that in the .edmx file.
Is there something I'm missing here?
Should I be creating my own classes that use the entities and put the logic in there?
It seems like there should be a way for me to do less work.
Thanks!
This can be achieved by using the buddy-class functionality in .NET implemented specifically for this reason. Once you have created your entities in your .ebmx file you can create partial classes to accompany your entities which define your business rules in a 'buddy class'.
[MetadataType(typeof(ProductMetadata))]
public partial class Product {
internal sealed class ProductMetadata {
[DisplayName("Name")]
[Required]
public string Name { get; set; }
[DispayName("Price")]
[Required, Range(1,10000)]
public decimal Price { get; set; }
[DisplayName("Description")]
public string Description { get; set; }
}
}
In the example above, assume that you already have a "Product" type defined in your object context which has properties for "Name", "Price", and "Description". So long as the buddy class type referenced by the MetadataTypeAttribute has matching property names, the attributes applied to the properties in the buddy class will be applied to the implementation type.
Note: if there are any property names in the buddy class which do not match the implementation type, you will get a runtime error. You only need to create matching properties in the buddy class for the properties you are interested in applying business rules to; all properties are optional.