I have following Category table as below and I have use Entity framework model first:
ID => int , primary key , unique
CategoryName => varchar(50)
ParentCategoryID => int
I have applied unique constraint for two column categoryName and ParentCategoryID by executing following query:
ALTER TABLE Category
ADD CONSTRAINT UQ_YourTable_ConstraintName UNIQUE(CategoryName, ParentCategoryID)
Here, what I want is that to validate the input if the commbine form of categoryName and ParentCategoryID is unique using dataannotation. So, I have created the partial class for category as:
[MetadataType(typeof(TestEntityValidation))]
public partial class Category{
}
public class TestEntityValidation{
//............ data annotation
public string CategoryName{ get; set; }
//............ data annotation
public string ParentCategoryID { get; set; }
}
what could be code for data annotation so that Combination of CategoryName and ParentCategoryID is always unique and show error if duplicate data is entered by user.
I dont think you can do this using Data Annotation, but here is what you could do
public ActionResult Validate(SomeModel model)
{
// check for this condition with db using the 'model'
if(combination_is_NOT_unique)
{
ViewBag.Message = "Not Unique";
return View("NameOfTheView");
}
// else
do the normal stuff
}
Related
I have two entities
public class Datatype
{
[Key]
public int Id { get; set; }
[StringLength(96)]
public string DataTypeName { get; set; }
}
public class Attribute
{
[Key]
public int Id { get; set; }
[StringLength(96)]
public string Attribute_Name { get; set; }
[ForeignKey("Datatype")]
public int? DatatypeId { get; set; }
public virtual Datatype Datatype { get; set; }
}
In DataBase Initialize I have this code
Datatype dt = new Datatype();
dt.DataTypeName = "text";
context.datatypes.Add(dt);
//Above code is working fine. And After execution I can see
//in records a row.. with id=1 and datatype=text
Attribute at = new Attribute();
at.Attribute_Name = "Description";
//at.DatatypeId = 1; But if I uncomment this line
context.attributes.Add(at); // Then This Gives Following Error
The INSERT statement conflicted with the FOREIGN KEY constraint
"FK_dbo.Attributes_dbo.Datatypes_DatatypeId". The conflict occurred in database
"dyescan", table "dbo.Datatypes", column 'Id'
Assuming that the above code executes before either of the two objects have been saved to the database then it will not work simply because your object 'dt' will not have an ID of 1 before it's been saved to the database and therefore you cannot associate with attribute on '1' YET!
Instead you should not set the 'DatatypeId' but simply set the 'Datatype' like so:
at.Datatype = dt;
This will leave entity framework to figure out what the actual foreign key associated should/would be when savechanges is called.
I am using MVC4 ,T4 Scaffolding and EF5.
I Created a model,
namespace wbtest.Models
{
[Table(name: "Pay_Employees_Mst", Schema = "Test")]
public class Employee
{
public int EMPLOYEE_ID { get; set; }
public string EMPLOYEE_CODE { get; set; }
}
}
I need to get the annotation of table name "Pay_Employees_Mst" for db context .Currently getting ModelName Employee.
Please Help.
I got it through,
String entityName1 = (context as System.Data.Entity.Infrastructure.IObjectContextAdapter).ObjectContext
.CreateObjectSet<Employee>()
.EntitySet.Name;
I'm using a context generated from an EDMX for a mvc3 webapp. I'm getting a NULL insert fails error on an entity
[Serializable]
[DataContract(IsReference = true)]
[EdmEntityType(NamespaceName = "Model", Name = "Thing")]
public class Thing: EntityObject
{
public RolloverEntry();
[DataMember]
[EdmScalarProperty(EntityKeyProperty = true, IsNullable = false)]
public int id { get; set; }
[SoapIgnore]
[EdmRelationshipNavigationProperty("Model", "FK_ThingStep1", "Step1")]
[DataMember]
[XmlIgnore]
public EntityCollection<Step1> Step1 { get; set; }
[SoapIgnore]
[EdmRelationshipNavigationProperty("Model", "FK_ThingStep2", "Step2")]
[XmlIgnore]
[DataMember]
public EntityCollection<Step2> Step2 { get; set; }
public static Thing CreateThing(int id);
}
Data access to other parent-child relationships are working and persisted correctly - I can't seem to find what's wrong with this table tho - any ideas appreciated
Exception Recieved:
{"Cannot insert the value NULL into column 'id', table 'myapp.dbo.Thing'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."}
Thanks
I'm guessing you need some sort of hint in your model that the database should generate the ids for the id column. You might want to see if StoreGeneratedPattern is set to Identity for your model property id or something along those lines.
Hi I have a few more questions on MVC3 Model and App_data.
I want to add two columns to my table, say lat, and lon. I can do that from sql script.
But after adding these two columns, how can I update the Model so the new columns will be the members of the Model?
I have a list of articles I want to display, what's the reliable way to display them in one view, instead of creating one view for each article?
Thanks a lot!
Answer to question 1:
Simply update your view model to store the additional fields. For example:
public class IndexModel
{
//existing fields
public string Name { get; set; }
public string Address { get; set; }
//etc
//your new fields
public string lat { get; set; } //use the preferred type
public string lon { get; set; }
}
Then, in the controller action you can update the model with the new fields from the database using entity framework or however you choose to connect to the database.
public class HomeController : Controller
{
public ActionResult
{
IndexModel model = //retrieve model from database here...
return View(model);
}
}
Ok - first off apologies - I'm a front end developer (HTML, CSS and JS) trying to do stuff with data - never pretty!
I have a 'Page', that can can have one or many 'Series'. These 'Series' can hold one or many 'Collections' and these 'Collections' can be related to more than one 'Series'. The 'Collection's can hold one or more 'Titles'. This is how I've structured my db:
CREATE TABLE [dbo].[Pages] (
PageId INT NOT NULL PRIMARY KEY,
[Title] NCHAR(50) NOT NULL
)
CREATE TABLE [dbo].[Series] (
[SeriesId] INT NOT NULL,
[Title] NCHAR (50) NOT NULL,
[PageId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([SeriesId] ASC),
CONSTRAINT [FK_Series_Pages] FOREIGN KEY ([PageId]) REFERENCES [Pages]([PageId])
);
CREATE TABLE [dbo].[Collections] (
[CollectionId] INT NOT NULL,
[Title] NCHAR (50) NOT NULL,
PRIMARY KEY CLUSTERED ([CollectionId] ASC)
);
CREATE TABLE [dbo].[SeriesCollections] (
[SeriesCollectionId] INT NOT NULL,
[SeriesId] INT NOT NULL,
[CollectionId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([SeriesCollectionId] ASC),
CONSTRAINT [FK_SeriesCollections_Series] FOREIGN KEY ([SeriesId]) REFERENCES [Series]([SeriesId]),
CONSTRAINT [FK_SeriesCollections_Collections] FOREIGN KEY ([CollectionId]) REFERENCES [Collections]([CollectionId])
);
CREATE TABLE [dbo].[Titles] (
[TitleId] INT NOT NULL,
[Title] NCHAR (100) NOT NULL,
[SeriesCollectionId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([TitleId] ASC),
CONSTRAINT [FK_Titles_SeriesCollections] FOREIGN KEY ([SeriesCollectionId]) REFERENCES [SeriesCollections]([SeriesCollectionId])
Using Entity Framework I have the following:
public DbSet<Page> Pages { get; set; }
public DbSet<Series> Series { get; set; }
public DbSet<Collection> Collections { get; set; }
public DbSet<SeriesCollection> SeriesCollections { get; set; }
public DbSet<Title> Titles { get; set; }
In the view I want to get the following.
For a given 'Page' (id), I want all the 'Series' and within each of those 'Series', be able to list each of the 'Titles' and its associated 'Collection'.
First off - is my db set up correctly? Secondly, I'm struggling with the db call and viewmodels that would return this.
If anyone can help that'd be great
Thanks in advance
The 'Collection's can hold one or more 'Titles'.
Because of this I would modify your DB table schema:
In table Titles replace [SeriesCollectionId] by [CollectionId], directly refering to the Collections table.
In table SeriesCollections remove your PK [SeriesCollectionId] and make instead the remaining two fields [SeriesId] and [CollectionId] to a composite primary key.
Now, you can model a many-to-many relationship between Series and Collections with EF. Then the join table SeriesCollections isn't part of your model anymore. It's just a hidden table in the DB which is managed by EF. Therefore you can remove public DbSet<SeriesCollection> SeriesCollections { get; set; }.
The model classes could then look like this:
public class Page
{
public int PageId { get; set; }
[Required]
[MaxLength(50)]
pubic string Title { get; set; }
public ICollection<Series> Series { get; set; }
}
public class Series
{
public int SeriesId { get; set; }
[Required]
[MaxLength(50)]
pubic string Title { get; set; }
public int SeriesId { get; set; }
public int PageId { get; set; } // FK property, helpful but not required
public Page Page { get; set; }
public ICollection<Collection> Collections { get; set; }
}
public class Collection
{
public int CollectionId { get; set; }
[Required]
[MaxLength(50)]
pubic string Title { get; set; }
public ICollection<Series> Series { get; set; }
public ICollection<Title> Titles { get; set; }
}
public class Title
{
public int TitleId { get; set; }
[Required]
[MaxLength(100)]
pubic string TTitle { get; set; } // must be other name then class
public int CollectionId { get; set; } // FK property
public Collection Collection { get; set; }
}
For many-to-many mapping you need Fluent API:
public class MyContext : DbContext
{
public DbSet<Page> Pages { get; set; }
public DbSet<Series> Series { get; set; }
public DbSet<Collection> Collections { get; set; }
public DbSet<Title> Titles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Series>()
.HasMany(s => s.Collections)
.WithMany(c => c.Series)
.Map(a =>
{
a.MapLeftKey("SeriesId");
a.MapRightKey("CollectionId");
a.ToTable("SeriesCollections");
});
}
}
EF will figure out all other relationships by convention, I believe.
For a given 'Page' (id), I want all the 'Series' and within each of
those 'Series', be able to list each of the 'Titles' and its
associated 'Collection'.
With the model above you could then try:
var page = context.Pages.Where(p => p.PageId == id)
.Include(p => p.Series.Select(s => s.Collections.Select(c => c.Titles)))
.SingleOrDefault();
It would select the page which contains a list of series with a list of collections with a list of titles.
Not sure if this is exactly what you want, just an untested starting point.
(BTW: You can write your classes first (Code-First) and let EF create your database tables. It's easier during design phase when you want to try some mappings, imo.)
Edit
One thing I forgot: If you really want non-variable fixed length string fields (NCHAR(50)) you must define this explicitely in Fluent API. By default EF would assume NVARCHAR(50) fields with the mapping above. Setting to fixed length columns would look like this:
modelBuilder.Entity<Page>().Property(p => p.Title).IsFixedLength();