I'm writing a web app using Core 2.0 MVC. With the help of EF I'm trying to create (code first) models to model the database so I can automate the whole db creation process using migration.
My issue, I'm using a third party library to interact with an API (this library was built specifically to interact with this API) but the data that the API returns I'd like to store in a db using the same schema as the class from the library.
As an example
Third party library
public class PersonDetails
{
public long PersonID { get; set; }
public string PersonName { get; set; }
}
If i try to create a migration for this class it complains about no primary key being set, I'm unable to modify this class. Is there a way that I can set the [Key] attribute for PersonID from an inherited class or something similar?
Related
I want to create a Line-of-Business App in ASP.NET Core & (desirably) Razor Pages but have not managed to find a guide (or a starter project) that provides clear directives for how to handle complex CRUD functionality.
Given the following EF model:
public class Patient
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string IDNumber { get; set; }
public DateTime DateOfBirth { get; set; }
public virtual ICollection<PatientCard> PatientCardsCollection { get; set; }
}
public class PatientCard
{
public int Id { get; set; }
public int CardNumber { get; set; }
public Patient Patient { get; set; }
}
what I specifically haven't managed to find is how to create a ListView/DetailView for a Patient that has a collection of PatientCards, which should be displayed in a DetailView for Patient and allow creation / editing / linking of PatientCard-s to Patient, as shown here: Sample DetailView & nested ListView - in the screen Patient Business Object has a collection of PatientCard business objects.
Granted, this would likely require the utilization of some commercial components, like DevExtreme, Kendo, Syncfusion, etc. and we are ready to use any of those.
We have successfully used the DevExpress XAF framework with this purpose in the past, which creates stateful apps based on ASP.NET Forms and thus can not scale well. Here's a demo of what you can create in a matter of hours in it: https://demos.devexpress.com/XAF/MainDemo
We have also looked at other frameworks like the ASP.NET Zero ( https://aspnetzero.com ) and it seems promising but what we'd really like is to create this functionality from scratch.
I would split up the application logic and create a .NET Core MVC Application and a second project as .NET Core Web API (2).
So all database operations can be done using the Web Api and you can simply call the API in the MVC Application.
I'd advise you to use Angular, baselined into .NET Core MVC projects. This way your business applications provides a good user experience because it is a SPA.
You can put your backend engineers focused on a separate project => the web api and a team on the frontend/communication with the backend.
Hit me up if you have any questions!
The easy Solution would be a seperate list for the relation between Patient and PatientCard with it's own Detail.
Otherwise you can still implement your own logic in the Patient Detail to add, remove, edit patient cards. For example have a list with plus- and minus-button and field for the Card number on each row. You can achieve this using view component for the row. So every card you add is another "instance" of the View Components. Like in this example of a TodoList:
Have a look here: View Components Doc
I got a sqlite table in xamarain (native android / pcl):
[Table("Customer")]
public class Customer
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public Address Address{ get; set; }
}
"Address" represents a second table.
1) Is it possible to automatically create the "Address" Table when I call
connection.CreateTable<CustomerDto>();
because it is it's dependency?
2) Is it possible to use a LINQ expression which automatically maps the correct "Address" to this "Customer?
In my .NET Standard library I'm using:
"sqlite-net": "1.0.8"
"sqlite-net-pcl": "1.3.1"
My approach was to create "initial state models" of all the tables, marked as abstract (so there is no risk that somebody could instantiate them), defining only the fields necessary in the database and the primary keys (GUID in my case), used only to create tables at the beginning. Following modification to the data structures always with ALTER instructions.
In another namespace a duplication of all the models, this time with getters/setters and other utilities, and I used these as "real models".
For representing linked models I used a field as Id and another one as model (refreshed when necessary):
public int IdAddress { get; set; }
[Ignore]
public Address Address { get; set; }
I don't think sqlite-net can do what you are asking because it's a very lightweight orm, and even if it could I prefer don't automate too much because of my past experiences with Hibernate.
https://github.com/praeclarum/sqlite-net
https://components.xamarin.com/view/sqlite-net
It sounds like you should look at using Entity Framework because that will allow you to use LINQ with SQLite. The standard library on the web (not Entity framework) is very light and doesn't have much functionality for the ORM like functionality you are looking for.
If you're looking for a more lightweight library, you can use this, but it will not allow you to write LINQ expressions without writing your own ORM:
https://github.com/MelbourneDeveloper/SQLite.Net.Standard
I have a newly built MVC 5 app, using the default template, PayCaddy.Client. As built, without any mods, the project creates its own data model, covering entities like ApplicationUser for authentication. I like this, just create the project, and it's ready for me to do my own stuff and not worry too much about authentication.
Yet now, my own stuff includes a separate business data model, in a separate project, PayCaddy.Data, that includes entities like a bet in a golf game:
public class Bet: PayCaddyEntity
{
public virtual string BetName { get; set; }
public virtual int Amount { get; set; }
public virtual ApplicationUser Owner { get; set; }
public virtual DateTime OpenedOn { get; set; }
public virtual DateTime? ClosedOn { get; set; }
public ICollection<BetUser> Punters { get; set; }
}
Now ApplicationUser is used here to indicate the user that initiated the bet, which will be between them and the Punters. This leaves me stuck with a circular reference problem, where I need a reference to PayCaddy.Client for the ApplicationUser entity, and that project needs a reference back for the Bet entity.
The Identity framework is highly complex, and simply moving its entities into my data model is out of the question. For now, I have moved my data model into the client project, the same prokect as the Identity code, but I don't want to continue like that if there is a relatively simple way of overcoming this problem. If solutions without days of effort exist, what are they?
Could you try moving the ApplicationUser object out of the MVC project and moving it into your new project. That way all your models are in the one project and your MVC app can just have the one reference to the data project?
Edit by the OP: Just a warning: If you move ApplicationUser into your own data model, you must derive your DbContext from IdentityDbContext<ApplicationUser>, not plain old DbContext, and it's crucial that you call base.OnModelCreating(modelBuilder) in OnModelCreating. Normally the base method has no implementation, but here it has some 70 lines of configuration code that is essential to this data model.
I am following along Pro ASP.NET MVC 4 by Adam Freeman on VS 2010 (I downloaded the MVC 4 template online). I have worked with the .edmx file before, but in Chapter 7 he does not do this. I setup a basic connection string with SQL Server in my web.config file within my WebUI project where my controllers and views are located. Also, I listed my Domain classes within my Domain project below. The problem comes when I run the application. The application is not recognizing my table in my database (dbo.Request) and instead is creating a table based on my class name in the Entities namespace (so it creates a CustRequest table) and it also creates a _Migration_History table. To prevent this I add the Data Annotation above my class [Table("MyTableName")]. I could not figure out why I had to add this Data Annotation. Also, EF made me add a [Key] above my primary key, which i can understand because i do not have an ID property, but in the book he did not do this. I was wondering if I was missing something obvious as I am pretty new to MVC. Any help would be appreciated. I am working with EF 6. Thank you.
namespace Requestor.Domain.Entities
{
[Table("Request")]
public class CustRequest
{
[Key]
public int RequestId { get; set; }
public string RequestByUserCd { get; set; }
public DateTime RequestDateTime { get; set; }
public DateTime DueDate { get; set; }
}
}
namespace Requestor.Domain.Abstract
{
public interface ICustRequestRepository
{
IQueryable<CustRequest> Request { get; }
}
}
namespace ITRequestHub.Domain.Concrete
{
public class EFDbContext : DbContext
{
public DbSet<CustRequest> Request { get; set; }
}
}
namespace ITRequestHub.Domain.Concrete
{
public class EFCustRequestRepository : ICustRequestRepository
{
private EFDbContext context = new EFDbContext(); //retrieves the data
public IQueryable<CustRequest> Request
{
get { return context.Request; }
}
}
}
Consider trying again with EF5 if you can, I experienced similar issues when trying to make EF6 work with MVC4 (I couldn' make scaffolding work either).
Or go all the way up to the latest versions for everything and try MVC5 with EF6 (this seems to work fine)
You've run into the wonderful and sometimes frustrating part of EF, its conventions. Wonderful when you're aware of the conventions as they simplify life, but frustrating when you feel that the framework is performing tasks without your explicit permission.
Firstly, additional information on EF6 conventions can be found here: http://msdn.microsoft.com/en-gb/data/jj679962.aspx
On your first point, as far as I'm aware, EF takes the name of your entity as the name of the table it will create in your DB. As you've discovered, you do have control over this via the "Table" attribute, but you can also control it's desire to want to pluralize your entity names when creating tables by means convention removal within your DbContext
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>()
On your second point, I cannot imagine that you would require a "Key" attribute attached to your "RequestId" field. The convention here is that if the field name contains a suffix of ID (case-insensitive), then EF will automatically include it as a primary key and if the type of the field is either an Int or a Guid it will be automatically set as an auto-seed identity column.
I am working on a project utilizing MVC4 and EF Data First in VS2012. The table has a primary key which does not have "id" in the field name so EF does not understand it should use it as the primary key. After EF generates the code I add the following annotations and using statements.
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public partial class Game
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int GameNumber { get; set; }
If I base my models from the generate code the custom changes I make will be discard if I update the database models. How can I keep my custom changes and update the database EF data model.
Thanks
use MetadataTypeAttribute (MSDN) to define a metadata class on a partial implementation of your entity class, then decorate the properties in that metadata class.
Note that the decorated partial class implementation should exist in a file other than the autogenerated file so as to persist refreshing from DB.
(question: if your model is DB first, why doesn't it know what the PK is for the Game table? Whether or not the property has Id at the end doesn't matter when it's reading the table schema to generate the model...)
[MetadataType("GameMetadata")]
public partial class Game
{
public class GameMetadata
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int GameNumber;
}
}