I am learning EF Code First from "Programming Entity Framework Code First". The following code snippets are copied from page 5 to page 7.
Visit.cs
using System;
namespace ChapterOne
{
class Visit
{
public int Id { get; set; }
public DateTime Date { get; set; }
public String ReasonForVisit { get; set; }
public String Outcome { get; set; }
public Decimal Weight { get; set; }
public int PatientId { get; set; }
}
}
AnimalType.cs
namespace ChapterOne
{
class AnimalType
{
public int Id { get; set; }
public string TypeName { get; set; }
}
}
Patient.cs
using System;
using System.Collections.Generic;
namespace ChapterOne
{
class Patient
{
public Patient()
{
Visits = new List<Visit>();
}
public int Id { get; set; }
public string Name { get; set; }
public DateTime BirthDate { get; set; }
public AnimalType AnimalType { get; set; }
public DateTime FirstVisit { get; set; }
public List<Visit> Visits { get; set; }
}
}
VetContext.cs
using System.Data.Entity;
namespace ChapterOne
{
class VetContext : DbContext
{
public DbSet<Patient> Patients { get; set; }
public DbSet<Visit> Visits { get; set; }
}
}
Program.cs
using System;
using System.Collections.Generic;
namespace ChapterOne
{
class Program
{
static void Main(string[] args)
{
var dog = new AnimalType { TypeName = "Dog" };
var patient = new Patient
{
Name = "Simpson",
BirthDate = new DateTime(2008, 1, 28),
AnimalType = dog,
Visits = new List<Visit>
{
new Visit
{
Date = new DateTime(2011, 9, 1)
}
}
};
using (var context = new VetContext())
{
context.Patients.Add(patient);
context.SaveChanges();
}
}
}
}
Unfortunately, I got the following error. Could you tell me what is wrong?
Probably you're not filling all required fields. The one i noticed is Patient.FirstVisit default value is not acceptable by sql server.
Not sure if this is the cause of your exact error, but will probably cause another error too; Your VetContext should contain 1 more line:
public DbSet<AnimalType> AnimalTypes { get; set; }
Otherwise, EF won't make an AnimalType table in the DB to insert the
var dog = new AnimalType { TypeName = "Dog" };
record into.
Related
I have two list that have been returned from two separate tables in a SQL server database using dapper lstPart and lstSite. Both lists have a ITEMNUM field which correspond with each other. In the part list the ITEMNUM field is unique but in the Site list it is not. Some parts have multiple sites some have none.
using System;
namespace CWIC_Data_Framework.Definition.MP2Definitions
{
public class MP2BaseTableDefinition
{
public string ITEMNUM { get; set; }
public string? DESCRIPTION { get; set; }
public string? NOTES { get; set; }
public string? UOM { get; set; }
public DateTime? DATEADDED { get; set; }
public DateTime? LASTEDITDATE { get; set; }
public string? COMMENTS { get; set; }
public string? SITE { get; set; }
public string? LOCATION { get; set; }
public int? QTYONHAND { get; set; }
}
}
using System;
namespace CWIC_Data_Framework.Definition.MP2Definitions
{
public class MP2SiteTableDefinition
{
public string ITEMNUM { get; set; }
public int? REORDERPOINT { get; set; }
public int? REORDERQTY { get; set; }
public string? SITE { get; set; }
public DateTime? LASTDATECOUNTED { get; set; }
public DateTime? LASTDATERCVD { get; set; }
public DateTime? LASTACTIVITY { get; set; }
}
}
I am creating an app with C# WPF and I would like to have a final result similar to this.
Example Of What I'm looking for
I think I need to create a single list that contains the site list as a sublist to the parts list using LINQ and then bind it to a Datagrid but I am not positive.
public class Part
{
public int PartID { get; set; }
public string Description { get; set; }
public list<site> Location { get; set; }
}
Any help or direction would be appreciated.
Here is the class for calling one of the list (The part list) , the other is the same.
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using CWIC_Data_Framework.Definition.MP2Definitions;
using Dapper;
using SerilogTimings;
namespace CMMS_Status.Data
{
internal class MP2BaseTableData
{
private static string ThisMethod;
private string ThisClass;
public List<MP2BaseTableDefinition> ListOfMp2Base(Dictionary<string, object> paramDictionary)
{
ThisMethod = MethodBase.GetCurrentMethod().Name;
using (var op = Operation.Begin("{Class}{Method}", ThisClass, ThisMethod))
using (IDbConnection connection = new SqlConnection(Helper.ConnectionValue("CreeMesRtp")))
{
var parameters = new DynamicParameters(paramDictionary);
var SQL = #"
Select
CMMSSB.MP2_INVY.ITEMNUM,
CMMSSB.MP2_INVY.DESCRIPTION,
CMMSSB.MP2_INVY.UOM,
CMMSSB.MP2_INVY.NOTES,
CMMSSB.MP2_INVY.DATEADDED,
CMMSSB.MP2_INVY.LASTEDITDATE,
CMMSSB.MP2_INVCOMM.COMMENTS,
CMMSSB.MP2_STOCK.SITE,
CMMSSB.MP2_STOCK.LOCATION,
CMMSSB.MP2_STOCK.QTYONHAND
From
CMMSSB.MP2_INVY Inner Join
CMMSSB.MP2_STOCK On CMMSSB.MP2_STOCK.ITEMNUM = CMMSSB.MP2_INVY.ITEMNUM Left Join
CMMSSB.MP2_INVCOMM On CMMSSB.MP2_INVCOMM.ITEMNUM = CMMSSB.MP2_INVY.ITEMNUM
";
var Output = connection.Query<MP2BaseTableDefinition>(SQL, parameters).ToList();
op.Complete();
return Output;
}
}
}
}
The class for pulling the Site info.
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using CMMS_Status.Definition;
using CWIC_Data_Framework.Definition.MP2Definitions;
using Dapper;
using SerilogTimings;
namespace CMMS_Status.Data
{
internal class MP2SiteTableData
{
private static string ThisMethod;
private string ThisClass;
public List<MP2SiteTableDefinition> ListOfMp2Site(Dictionary<string, object> paramDictionary)
{
ThisMethod = MethodBase.GetCurrentMethod().Name;
using (var op = Operation.Begin("{Class}{Method}", ThisClass, ThisMethod))
using (IDbConnection connection = new SqlConnection(Helper.ConnectionValue("CreeMesRtp")))
{
var parameters = new DynamicParameters(paramDictionary);
var SQL = #"
Select
CMMSSB.MP2_SITEINFO.ITEMNUM,
CMMSSB.MP2_SITEINFO.REORDERPOINT,
CMMSSB.MP2_SITEINFO.REORDERQTY,
CMMSSB.MP2_SITEINFO.LASTDATECOUNTED,
CMMSSB.MP2_SITEINFO.LASTDATERCVD,
CMMSSB.MP2_SITEINFO.LASTACTIVITY
From
CMMSSB.MP2_SITEINFO
";
var Output = connection.Query<MP2SiteTableDefinition>(SQL, parameters).ToList();
op.Complete();
return Output;
}
}
}
}
Update: I have checked the below code
But why you changed full description??
public class Site
{
public int PartID { get; set; }
public string Location { get; set; }
}
public class Part
{
public int PartID { get; set; }
public string Description { get; set; }
public List<Site> Location { get; set; }
}
var siteList = new List<Site>() {
new Site{PartID = 1, Location = "Dhaka"},
new Site{PartID = 2, Location = "Rajshahi"},
new Site{PartID = 3, Location = "Khulna"},
new Site{PartID = 2, Location = "Barisal"},
new Site{PartID = 1, Location = "Narsingdi"},
};
var dictionary = siteList.GroupBy(s => s.PartID)
.ToDictionary(s => s.Key,
s => s.ToList());
var partList = new List<Part> (){
new Part{ PartID = 3, Description = "A", Location = null},
new Part{ PartID = 2, Description = "C", Location = null},
new Part{ PartID = 1, Description = "B", Location = null},
};
foreach(var part in partList)
{
part.Location = dictionary[part.PartID];
}
I created a database, then applied dataase-first. Then it automatically imported the database to VS. Please tell me, when database-first automatically indicates relationship? Probably not, my data is not being imported. Could you tell me how to establish connections correctly? I read about the fluent api and about the fact that you can specify keys and properties directly in the table classes (And when is it better to do through fluent, and when to specify directly?)
My 1st table
namespace WcfRestFullService.Model
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Web;
[DataContract]
public partial class customer
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public customer()
{
this.dishesrankings = new HashSet<dishesranking>();
this.orders = new HashSet<order>();
}
[DataMember]
public int Id_Cus { get; set; }
[DataMember]
public string FirstName_Cus { get; set; }
[DataMember]
public string LastName_Cus { get; set; }
[DataMember]
public int PhoneNum_Cus { get; set; }
[DataMember]
public string Email_Cus { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<dishesranking> dishesrankings { get; set; }
public virtual customerpreference customerpreference { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<order> orders { get; set; }
}
}
My 2nd table
namespace WcfRestFullService.Model
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Runtime.Serialization;
using System.Web;
[DataContract]
public partial class customerpreference
{
[DataMember]
public int Id_Cus { get; set; }
[DataMember]
public int Id_Res { get; set; }
[DataMember]
public string Name_Dis { get; set; }
[DataMember]
public int Id_Type { get; set; }
public virtual customer customer { get; set; }
public virtual order order { get; set; }
public virtual type_dishes type_dishes { get; set; }
}
}
MySQLEntities
namespace WcfRestFullService.Model
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class MySQLEntities : DbContext
{
public MySQLEntities()
: base("name=MySQLEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<customer>()
.HasMany(c => c.customerpreference)
.WithOptional(o => o.Customer);
//throw new UnintentionalCodeFirstException();//here problem
}
public virtual DbSet<customer> customers { get; set; }
public virtual DbSet<customerpreference> customerpreferences { get; set; }
public virtual DbSet<dish> dishes { get; set; }
public virtual DbSet<dishesranking> dishesrankings { get; set; }
public virtual DbSet<ingridient> ingridients { get; set; }
public virtual DbSet<order> orders { get; set; }
public virtual DbSet<restaraunt> restaraunts { get; set; }
public virtual DbSet<type_dishes> type_dishes { get; set; }
public object Parameters { get; internal set; }
}
}
Here I create data(Id_Cus) but it doesn't import in 2nd table
public void InsertCustomer(customer customerDataContract)
{
//MySQLEntities Cust = new MySQLEntities();
customer cust = new customer();
{
cust.Id_Cus = Convert.ToInt32(customerDataContract.Id_Cus);
cust.FirstName_Cus = customerDataContract.FirstName_Cus;
cust.LastName_Cus = customerDataContract.LastName_Cus;
cust.PhoneNum_Cus = Convert.ToInt32(customerDataContract.PhoneNum_Cus);
cust.Email_Cus = customerDataContract.Email_Cus;
};
dc.customers.Add(cust);
customerpreference custPref = new customerpreference()
{
Id_Cus = customerDataContract.Id_Cus,
Id_Res = 0, // some value
Name_Dis = null, // some value
Id_Type = 0 // some value
};
dc.customerpreferences.Add(custPref);
dc.SaveChanges();
int k = Convert.ToInt32(cust.Id_Cus);
customer custFromDb =(from n in dc.customers
where n.Id_Cus == k
select n).Include(c => c.customerpreference).First();
}
perhaps problem in
cust = (from n in dc.customers
where n.Id_Cus == k
select n).Include(c =>c.customerpreference).ToList().First();
dc.customers.Add(cust);
dc.SaveChanges();
Yes it does automatically model foreign keys. You can see that it has done so in your model because there are navigation properties such as dishesrankings in your Customer class.
We had a database first project. We would update it by changing the database using dbup and then updating the model from the database. This way you ensure consistency between the model and the database.
DbUp: https://dbup.github.io/
DbUp is a tool to run scripts to make changes to the database that allows versioning and rollback and it is very useful if you're using database first.
I have a probably simple question, I am trying to create many to many relationships using entity framework and fluent api, and my problem is that when i try to do any query or view a object in debug it has always 0 items.
I am using junction table that looks like:
So relations exists, to be sure ive checked:
select candidate.firstname, skillset.name
from candidate
join candidate_skillset on candidate.id = candidate_skillset.candidate_id
join skillset on candidate_skillset.skillset_id = skillset.id
and joined results are displayed.
Now my context looks like:
public class CatalogContexct : DbContext
{
public DbSet<Candidate> Candidates { get; set; }
public DbSet<SkillSet> SkillSets { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Candidate>().HasMany(t => t.SkillSets).WithMany(t => t.Candidates)
.Map(m =>
{
m.ToTable("candidate_skillset");
m.MapLeftKey("candidate_id");
m.MapRightKey("skillset_id");
});
modelBuilder.Entity<SkillSet>().ToTable("skillset");
modelBuilder.Entity<Candidate>().ToTable("candidate");
}
}
My left side model candidates:
[Table("candidate")]
public class Candidate
{
public Candidate()
{
this.SkillSets = new HashSet<SkillSet>();
}
[Key]
public int id { get; set; }
[Column("firstname")]
public string Firstname { get; set; }
public int? commendation_id { get; set; }
[ForeignKey("commendation_id")]
public Commendation commendation { get; set; }
public ICollection<SkillSet> SkillSets { get; set; }
}
And my rightside model skillset:
[Table("skillset")]
public class SkillSet : SimpleDictionary
{
public SkillSet()
{
this.Candidates = new HashSet<Candidate>();
}
public virtual ICollection<Candidate> Candidates { get; set; }
}
and that model has a parent class:
public class SimpleDictionary
{
[Key]
public int id { get; set; }
[Column("name")]
public string Name { get; set; }
}
So all should work but when I do for example:
var ca = this._catalog.Candidates
.Include("SkillSets").Include("commendation").
FirstOrDefault(x => x.SkillSets.Any());
Result is null, also when I view object on debug collection of property skillset allays has 0 elements, any idea what could be wrong with it?
I tried this with same structure mentioned here in you question and tried locally . And I am able to get the data with this code . Please try this and let me know if this helps . I just omitted commendation table for simplicity .
var context = new SampleDbContext();
var candidates = context.Candidates
.Include("SkillSets").ToList();
foreach (var candidate in candidates)
{
foreach (var sk in candidate.SkillSets.Where( s1 => s1.Candidates.Count(c=>c.id == candidate.id)>0 ))
{
Console.WriteLine( string.Format(#" Name : {0} Skill :{1}",candidate.Firstname ,sk.Name ) );
}
}
Below is my DbContext and Other Entity Classes
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
public class SampleDbContext : DbContext
{
public SampleDbContext()
: base("name=SampleDBConnection")
{
this.Configuration.LazyLoadingEnabled = false;
}
public DbSet<Candidate> Candidates { get; set; }
public DbSet<SkillSet> SkillSets { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Candidate>().HasMany(t => t.SkillSets).WithMany(t => t.Candidates)
.Map(m =>
{
m.ToTable("candidate_skillset");
m.MapLeftKey("candidate_id");
m.MapRightKey("skillset_id");
});
modelBuilder.Entity<SkillSet>().ToTable("skillset");
modelBuilder.Entity<Candidate>().ToTable("candidate");
}
}
[Table("candidate")]
public class Candidate
{
public Candidate()
{
this.SkillSets = new HashSet<SkillSet>();
}
[Key]
public int id { get; set; }
[Column("firstname")]
public string Firstname { get; set; }
public int? commendation_id { get; set; }
//[ForeignKey("commendation_id")]
//public Commendation commendation { get; set; }
public ICollection<SkillSet> SkillSets { get; set; }
}
public class SimpleDictionary
{
[Key]
public int id { get; set; }
[Column("name")]
public string Name { get; set; }
}
[Table("skillset")]
public class SkillSet : SimpleDictionary
{
public SkillSet()
{
this.Candidates = new HashSet<Candidate>();
}
public virtual ICollection<Candidate> Candidates { get; set; }
}
}
The output of the query you mentioned and the result of my code both matched I hope this is that you wanted .
I've just started working with MongoDB for c# and I'm trying to upsert some documents in a collection. I'm using the 'save' command (and even tried update with upsert flag on) but every time I run my code it keeps inserting duplicates: the new records have new object ids (randomly generated) but all the rest of the data is the same. What am I doing wrong? Any suggestion is greatly appreciated.
Here's my code:
List<LatestDataReduced> latestdata = new List<LatestDataReduced>();
//LatestDataReduced is the model of my documents
foreach (var dep in lrd)
{
foreach (var rec in dep.record)
{
var entity = new LatestDataReduced();
entity.PlatformID = platid;
//fill up data in entity...
latestdata.Add(entity);
}
}
var connectionString = "mongodb://localhost";
var client = new MongoClient(connectionString);
var server = client.GetServer();
var database = server.GetDatabase("emodnet2");
var collection = database.GetCollection<LatestDataReduced>("latestdata");
foreach (var ld in latestdata)
{
/*var query = Query.And(Query.EQ("Id", ld.Id), Query.EQ("Date", ld.Date), Query.EQ("Depth", ld.Depth), Query.EQ("PlatformID", ld.PlatformID), Query.EQ("Pressure", ld.Pressure));
var update = Update.Replace(ld);
collection.Update(query, update, UpdateFlags.Upsert);*/
collection.Save(ld);
}
LatestDataReduced class:
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MongoDB.Models
{
public class CodeValuePair
{
public string Code { get; set; }
public double Value { get; set; }
}
public class LatestDataReduced
{
//[BsonIgnoreIfDefault]
public ObjectId Id { get; set; }
public int PlatformID { get; set; }
public DateTime Date { get; set; }
public double Depth { get; set; }
public List<CodeValuePair> ParamValue { get; set; }
public double Pressure { get; set; }
public List<CodeValuePair> ParamValueInfo { get; set; }
public string Roos { get; set; }
}
}
I found a way to make this work!
I thought it was mandatory to use the class "ObjectId" for Ids in mongo and I was not able to give a real identifier to my documents, but then I found out you can simply use a String Id:
public class LatestDataReduced
{
//[BsonIgnoreIfDefault]
public String Id { get; set; }
public int PlatformID { get; set; }
public DateTime Date { get; set; }
public double Depth { get; set; }
public List<CodeValuePair> ParamValue { get; set; }
public double Pressure { get; set; }
public List<CodeValuePair> ParamValueInfo { get; set; }
public string Roos { get; set; }
}
so I gave my documents a valid identifier and mongo is now able to recognize equal documents correctly and update them instead of inserting them.
Thank you very much for your attention!
Have a nice monday
I need after loading the data from a model, automatically insert an information on a property of this type which do not come from the DB.
Exemple:
namespace project.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
public partial class MessageSource
{
public MessageSource()
{
this.messages = new HashSet<Message>();
}
public int id { get; set; }
public string category { get; set; }
public string message { get; set; }
public string message_translation { get; set; }
public virtual ICollection<Message> messages { get; set; }
}
}
id, category and message are DB table properties, message_translation no, after loading this model, always I will need to put automatically information in message_translation. How?
I do this:
public partial class MessageSource
{
public MessageSource()
{
this.messages = new HashSet<Message>();
}
public int id { get; set; }
public string category { get; set; }
public string message { get; set; }
public string message_translation { get; set; }
public virtual ICollection<Message> messages { get; set; }
public string getTranslate()
{
if(message_translation == null)
{
Message msg = messages.FirstOrDefault(m => m.language.Equals(Translate.Instance.getLanguage()));
if(msg != null)
{
message_translation = msg.translation;
}
else
{
message_translation = String.Empty;
}
}
return message_translation;
}
}
works good
public partial class MessageSource
{
private string _defaultLanguage;
public MessageSource(string defaultLang)
{
this.messages = new HashSet<Message>();
this._defaultLanguage = defaultLanguage ;
}
public int id { get; set; }
public string category { get; set; }
public string message { get; set; }
public string message_translation { get;
set{ value = getTranslation(_defaultLnag); }
public virtual ICollection<Message> messages { get; set; }
public string getTranslate(string lang)
{
var Translation = dbcontext.messages.Where(m=> m.Id == this.Id).FirstOrDefault().Translation.Where(t=>t.lang == lang).FirstOrDefault();
return Translation;
}
}
this solution assume that you are saving the translations in a separate table linked to the messages tables
messageSource m = new messageSource();
var m2 = // query your db using sql or entity framework
Then
m.id= m2.id;
m.category= m.category;
m.message= m2.message
m.message_translation= "vvvvvvv whatever"//do add thing here
m.messages = m2.messages;
Edit:
Another solution
Public class translation {
public int Id { get; set;}
public string language { get; set;}
public string text { get; set;}
}
Then you add in your messageSource model the following after removing message_translation
Public Icollection<translation> transMsg { get; set;}
Now suppose you have a msg that is translated into 13 languages; then the ICollection<transMsg> will have 13 item, and we need only the chinese translation
Do as follow:
First get your message
var myMsg = dbContext.messageSources.Where(m=>m.id== 6).FirstOrDefault();
This will not load any translation bec. We didnt use Include() , i.e. lazy loading
However, when we want the translation we pull it via another Linq query as follow:
var myMsgTranslation = myMsg.transMsgs.Where(t=>t.lang == "chinese").FirstOrDefault();
Or you load all the translations as follow
var myMsg = dbContext.messageSources.Where(m=>m.id== 6).Include(m=>m.msgTrans).FirstOrDefault();
And in yor View page u pull the default language as follow
#html.textBoxFor(model=>model.msgTrans.Where(t=>t.lang == "chinese"))
Desclaimer: not tested
Hope that help