we're working on a database for our study project, and we've got unexpected error while adding data to a table.
using (var ctx = new BazyDanychContext())
{
Osoba tmpTask = new Osoba { Imie = ImieLbl.Text, Nazwisko = NazwiskoLbl.Text, Telefon = TelefonLbl.Text, Adres = AdresLbl.Text, Mail = MailLbl.Text, IloscTransakcji = Int32.Parse(IloscLbl.Text), Typ = TypList.Text };
ctx.Osoba.Add(tmpTask);
ctx.SaveChanges();
}
We also tried:
To add new records using ExecuteSqlCommand, which worked just fine
ctx.Database.ExecuteSqlCommand("INSERT INTO dbo.Osoba VALUES('0','jan','nowak', '222222', 'adres', 'mail', '2', 'osoba')");
Using ctx.Entry(tmpTask).State = System.Data.Entity.EntityState.Added; (and also .Modified)
Typing the values manually (like in the ExecuteSqlCommand line)
No matter what we do, ctx.SaveChanges() gives us
OptimisticConcurrencyException: Store update, insert, or delete statement affected an unexpected number of rows (0).
Our classes:
namespace BazyDanych
{
public class BazyDanychContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
public BazyDanychContext() : base("ProjektBD")
{
Database.SetInitializer(new SQLdb());
}
public DbSet<Osoba> Osoba { get; set; }
}
}
namespace BazyDanych
{
public class Osoba
{
public int ID { get; set; }
public string Imie { get; set; }
public string Nazwisko { get; set; }
public string Telefon { get; set; }
public string Adres { get; set; }
public string Mail { get; set; }
public int IloscTransakcji { get; set; }
public string Typ { get; set; }
public override string ToString()
{
return "Imie: " + Imie + "\t Nazwisko: " + Nazwisko + "\t ID: " + ID.ToString();
}
}
}
Database table's structure looks like:
ID (int, null)
Imie (text, null)
Nazwisko (text, null)
Telefon (text, null)
Adres (text, null)
Mail (text, null)
IloscTransakcji (int, null)
Typ (text, null)
It looks like in your C# Entity Framework code, you are not including a value for ID, which would imply that you have it set to auto-increment as an IDENTITY value. However, in your INSERT statement, you include a value for it, which would not work if you had it set as an IDENTIY value. To solve your issue, you can do one of two things:
Change your ID column to auto-increment. This will allow you to keep your C# code as it is, and it should work as expected without supplying a value. Do this if you don't want to be directly responsible for the value inserted there.
Include a value in your EF code for the ID column:
using (var ctx = new BazyDanychContext())
{
Osoba tmpTask = new Osoba { ID = IDLbl.Text, Imie = ImieLbl.Text, Nazwisko = NazwiskoLbl.Text, Telefon = TelefonLbl.Text, Adres = AdresLbl.Text, Mail = MailLbl.Text, IloscTransakcji = Int32.Parse(IloscLbl.Text), Typ = TypList.Text };
ctx.Osoba.Add(tmpTask);
ctx.SaveChanges();
}
Related
I've tried to export the data of a csv file with c#(.NET version 4.5.2) and CSOM into a SharePoint Online list. My Problem is that I get this error:
Exception thrown: 'CsvHelper.TypeConversion.TypeConverterException' in CsvHelper.dll
Funktionäre.exe Error: 0 : Failed: The conversion cannot be performed.
Text: ''
MemberType: System.Single
TypeConverter: 'CsvHelper.TypeConversion.SingleConverter'
IReader state:
ColumnCount: 0
CurrentIndex: 11
HeaderRecord:
["ID","Anrede","Vorname","Nachname","Firma","Strasse","Ort","Postleitzahl","Land_Region","Fax","Telefon","Mitgliedsnummer","Benutzer2","Ortsgruppencode","Ortsgruppenname","Email","Initialen","Privat","Webseite","Legislatur"]
IParser state:
ByteCount: 0
CharCount: 315
Row: 2
RawRow: 2
Count: 20
RawRecord:
1;;Präsident und Max;;Hotel Nidum;Am Wiesenhang 1A;Mösern/Seefeld;6100;Österreich;;4,35E+13;;;;;info#nidum-hotel.com;P.;Aus;;2016
'Funktionäre.exe' (CLR v4.0.30319: Funktionäre.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\mscorlib.resources\v4.0_4.0.0.0_de_b77a5c561934e089\mscorlib.resources.dll'. Module was built without symbols.
Funktionäre.exe Error: 0 : Stack Trace: bei CsvHelper.TypeConversion.DefaultTypeConverter.ConvertFromString(String text, IReaderRow row, MemberMapData memberMapData)
bei CsvHelper.TypeConversion.SingleConverter.ConvertFromString(String text, IReaderRow row, MemberMapData memberMapData)
bei lambda_method(Closure )
bei CsvHelper.Expressions.RecordCreator.CreateT
bei CsvHelper.Expressions.RecordManager.CreateT
bei CsvHelper.CsvReader.d__871.MoveNext() bei System.Collections.Generic.List1..ctor(IEnumerable1 collection) bei System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)
bei ImportListFromCSV.Program.GetRecordsFromCsv() in C:\Users\DKienzl\source\repos\Funktionäre\Funktionäre\Program.cs:Zeile 164.
bei ImportListFromCSV.Program.Main() in C:\Users\DKienzl\source\repos\Funktionäre\Funktionäre\Program.cs:Zeile 44.
The program '[26296] Funktionäre.exe' has exited with code 0 (0x0).
Here is my code for Program.cs:
using System;
using System.IO;
using System.Configuration;
using System.Collections.Generic;
using System.Reflection;
using System.Diagnostics;
using System.Linq;
using System.Text;
using CsvHelper;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Utilities;
using Microsoft.SharePoint.Client.Taxonomy;
namespace ImportListFromCSV
{
class Program
{
const string csvPath = #"C:\Users\DKienzl\Documents\FDB\Faktuell_normalisiert.csv";
static void Main()
{
try
{
//Get site URL and credentials values from config
Uri siteUri = new Uri(ConfigurationManager.AppSettings["SiteUrl"].ToString());
var accountName = ConfigurationManager.AppSettings["AccountName"];
char[] pwdChars = ConfigurationManager.AppSettings["AccountPwd"].ToCharArray();
//Convert password to secure string
System.Security.SecureString accountPwd = new System.Security.SecureString();
for (int i = 0; i < pwdChars.Length; i++)
{
accountPwd.AppendChar(pwdChars[i]);
}
//Connect to SharePoint Online
using (var clientContext = new ClientContext(siteUri.ToString())
{
Credentials = new SharePointOnlineCredentials(accountName, accountPwd)
})
{
if (clientContext != null)
{
//Map records from CSV file to C# list
List<CsvRecord> records =
GetRecordsFromCsv();
//Get config-specified list
List spList = clientContext.Web.Lists.GetByTitle(ConfigurationManager.AppSettings["ListName"]);
foreach (CsvRecord record in records)
{
//Check for existing record based
on title (assumes Title should be unique per record)
CamlQuery query = new
CamlQuery();
query.ViewXml =
String.Format("#<View><Query><Where><Eq><FieldRef Name=\"ID\" />" +
"<Value Type=\"Text\">{0}
</Value></Eq></Where></Query></View>", record.ID);
var existingMappings = spList.GetItems(query);
clientContext.Load(existingMappings);
clientContext.ExecuteQuery();
switch (existingMappings.Count)
{
case 0:
//No records found, needs to be added
AddNewListItem(record, spList, clientContext);
break;
default:
//An existing record was found - continue with next item
continue;
}
}
}
}
}
catch (Exception ex)
{
Trace.TraceError("Failed: " + ex.Message);
Trace.TraceError("Stack Trace: " + ex.StackTrace);
}
}
private static void AddNewListItem(CsvRecord record, List spList, ClientContext clientContext)
{
//Instantiate dictionary to temporarily store field values
Dictionary<string, object> itemFieldValues = new Dictionary<string, object>();
//Use reflection to iterate through the record's properties
PropertyInfo[] properties = typeof(CsvRecord).GetProperties();
foreach (PropertyInfo property in properties)
{
//Get property value
object propValue = property.GetValue(record, null);
//Only set field if the property has a value
if (!String.IsNullOrEmpty(propValue.ToString()))
{
//Get site column that matches the property name
//ASSUMPTION: Your property names match the internal names of the corresponding site columns
Field matchingField = spList.Fields.GetByInternalNameOrTitle(property.Name);
clientContext.Load(matchingField);
clientContext.ExecuteQuery();
//Switch on the field type
switch (matchingField.FieldTypeKind)
{
case FieldType.User:
FieldUserValue userFieldValue = GetUserFieldValue(propValue.ToString(), clientContext);
if (userFieldValue != null)
itemFieldValues.Add(matchingField.InternalName, userFieldValue);
else
throw new Exception("User field value could not be added: " + propValue.ToString());
break;
case FieldType.Lookup:
FieldLookupValue lookupFieldValue = GetLookupFieldValue(propValue.ToString(),
ConfigurationManager.AppSettings["LookupListName"].ToString(),
clientContext);
if (lookupFieldValue != null)
itemFieldValues.Add(matchingField.InternalName, lookupFieldValue);
else
throw new Exception("Lookup field value could not be added: " + propValue.ToString());
break;
case FieldType.Invalid:
switch (matchingField.TypeAsString)
{
case "TaxonomyFieldType":
TaxonomyFieldValue taxFieldValue = GetTaxonomyFieldValue(propValue.ToString(), matchingField, clientContext);
if (taxFieldValue != null)
itemFieldValues.Add(matchingField.InternalName, taxFieldValue);
else
throw new Exception("Taxonomy field value could not be added: " + propValue.ToString());
break;
default:
//Code for publishing site columns not implemented
continue;
}
break;
default:
itemFieldValues.Add(matchingField.InternalName, propValue);
break;
}
}
}
//Add new item to list
ListItemCreationInformation creationInfo = new ListItemCreationInformation();
ListItem oListItem = spList.AddItem(creationInfo);
foreach (KeyValuePair<string, object> itemFieldValue in itemFieldValues)
{
if (itemFieldValues != null)
{
//Set each field value
oListItem[itemFieldValue.Key] = itemFieldValue.Value;
}
}
//Persist changes
oListItem.Update();
clientContext.ExecuteQuery();
}
private static List<CsvRecord> GetRecordsFromCsv()
{
List<CsvRecord> records = new List<CsvRecord>();
using (var sr = new StreamReader(csvPath))
{
var reader = new CsvReader(sr, System.Globalization.CultureInfo.CurrentCulture);
records = reader.GetRecords<CsvRecord>().ToList();
}
return records;
}
private static FieldUserValue GetUserFieldValue(string userName, ClientContext clientContext)
{
//Returns first principal match based on user identifier (display name, email, etc.)
ClientResult<PrincipalInfo> principalInfo = Utility.ResolvePrincipal(
clientContext, //context
clientContext.Web, //web
userName, //input
PrincipalType.User, //scopes
PrincipalSource.All, //sources
null, //usersContainer
false); //inputIsEmailOnly
clientContext.ExecuteQuery();
PrincipalInfo person = principalInfo.Value;
if (person != null)
{
//Get User field from login name
User validatedUser = clientContext.Web.EnsureUser(person.LoginName);
clientContext.Load(validatedUser);
clientContext.ExecuteQuery();
if (validatedUser != null && validatedUser.Id > 0)
{
//Sets lookup ID for user field to the appropriate user ID
FieldUserValue userFieldValue = new FieldUserValue();
userFieldValue.LookupId = validatedUser.Id;
return userFieldValue;
}
}
return null;
}
public static FieldLookupValue GetLookupFieldValue(string lookupName, string lookupListName, ClientContext clientContext)
{
//Ref: Karine Bosch - https://karinebosch.wordpress.com/2015/05/11/setting-the-value-of-a-lookup-field-using-csom/
var lookupList = clientContext.Web.Lists.GetByTitle(lookupListName);
CamlQuery query = new CamlQuery();
string lookupFieldName = ConfigurationManager.AppSettings["LookupFieldName"].ToString();
string lookupFieldType = ConfigurationManager.AppSettings["LookupFieldType"].ToString();
query.ViewXml = string.Format(#"<View><Query><Where><Eq><FieldRef Name='{0}'/><Value Type='{1}'>{2}</Value></Eq>" +
"</Where></Query></View>", lookupFieldName, lookupFieldType, lookupName);
ListItemCollection listItems = lookupList.GetItems(query);
clientContext.Load(listItems, items => items.Include
(listItem => listItem["ID"],
listItem => listItem[lookupFieldName]));
clientContext.ExecuteQuery();
if (listItems != null)
{
ListItem item = listItems[0];
FieldLookupValue lookupValue = new FieldLookupValue();
lookupValue.LookupId = int.Parse(item["ID"].ToString());
return lookupValue;
}
return null;
}
public static TaxonomyFieldValue GetTaxonomyFieldValue(string termName, Field mmField, ClientContext clientContext)
{
//Ref: Steve Curran - http://sharepointfieldnotes.blogspot.com/2013_06_01_archive.html
//Cast field to TaxonomyField to get its TermSetId
TaxonomyField taxField = clientContext.CastTo<TaxonomyField>(mmField);
//Get term ID from name and term set ID
string termId = GetTermIdForTerm(termName, taxField.TermSetId, clientContext);
if (!string.IsNullOrEmpty(termId))
{
//Set TaxonomyFieldValue
TaxonomyFieldValue termValue = new TaxonomyFieldValue();
termValue.Label = termName;
termValue.TermGuid = termId;
termValue.WssId = -1;
return termValue;
}
return null;
}
public static string GetTermIdForTerm(string term, Guid termSetId, ClientContext clientContext)
{
//Ref: Steve Curran - http://sharepointfieldnotes.blogspot.com/2013_06_01_archive.html
string termId = string.Empty;
//Get term set from ID
TaxonomySession tSession = TaxonomySession.GetTaxonomySession(clientContext);
TermStore ts = tSession.GetDefaultSiteCollectionTermStore();
TermSet tset = ts.GetTermSet(termSetId);
LabelMatchInformation lmi = new LabelMatchInformation(clientContext);
lmi.Lcid = 1033;
lmi.TrimUnavailable = true;
lmi.TermLabel = term;
//Search for matching terms in the term set based on label
TermCollection termMatches = tset.GetTerms(lmi);
clientContext.Load(tSession);
clientContext.Load(ts);
clientContext.Load(tset);
clientContext.Load(termMatches);
clientContext.ExecuteQuery();
//Set term ID to first match
if (termMatches != null && termMatches.Count() > 0)
termId = termMatches.First().Id.ToString();
return termId;
}
}
}
Here is my code for CsvRecord:
using System;
namespace ImportListFromCSV
{
public class CsvRecord
{
public float ID { get; set; }
public string Anrede { get; set; }
public string Vorname { get; set; }
public string Nachname { get; set; }
public string Firma { get; set; }
public string Strasse { get; set; }
public string Ort { get; set; }
public string Postleitzahl { get; set; }
public string Land_Region { get; set; }
public string Fax { get; set; }
public string Telefon { get; set; }
public float Mitgliedsnummer { get; set; }
public float Benutzer2 { get; set; }
public float Ortsgruppencode { get; set; }
public string Ortsgruppenname { get; set; }
public string Email { get; set; }
public string Initialen { get; set; }
public bool Privat { get; set; }
public string Webseite { get; set; }
public float Legislatur { get; set; }
}
}
And here is my App.config (but not with my real data of course):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0"
sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="SiteUrl" value="http://myWebsite/" />
<add key="AccountName" value="account.name#gmail.com"
/>
<add key="AccountPwd" value="Password123" />
<add key="ListName" value="Funktionaere" />
<add key="LookupListName" value="Lookup List" />
<add key="LookupFieldName" value="Title" />
<add key="LookupFieldType" value="Text" />
</appSettings>
</configuration>
Most code I got from this (I had to make some changes because its a bit older.):
https://github.com/ALCBerry87/SPO-Import-List-CSV
Here is the CSV-File I've been using:
https://drive.google.com/file/d/1GVQUr3G--PXLeFF0qMO3WQmDBeMeVDEh/view?usp=sharing
I hope someone can help me
Best regards
Daniel
The error message lets you know what the issue is. It is trying to convert empty text Text: '' into MemberType: System.Single. You can either make the properties Mitgliedsnummer, Benutzer2 and Ortsgruppencode nullable
public class CsvRecord
{
public float ID { get; set; }
public string Anrede { get; set; }
public string Vorname { get; set; }
public string Nachname { get; set; }
public string Firma { get; set; }
public string Strasse { get; set; }
public string Ort { get; set; }
public string Postleitzahl { get; set; }
public string Land_Region { get; set; }
public string Fax { get; set; }
public string Telefon { get; set; }
public float? Mitgliedsnummer { get; set; }
public float? Benutzer2 { get; set; }
public float? Ortsgruppencode { get; set; }
public string Ortsgruppenname { get; set; }
public string Email { get; set; }
public string Initialen { get; set; }
public bool Privat { get; set; }
public string Webseite { get; set; }
public float Legislatur { get; set; }
}
or you can give them a default value in mapping.
public class CsvRecordMap : ClassMap<CsvRecord>
{
public CsvRecordMap()
{
AutoMap(CultureInfo.InvariantCulture);
Map(x => x.Mitgliedsnummer).Default(0);
Map(x => x.Benutzer2).Default(0);
Map(x => x.Ortsgruppencode).Default(0);
}
}
I also noticed you are going to have an issue with the property Privat. It is a bool and is not going to be able to convert the value "Aus".
The data record in the exception seems to include some invalid data:
1;;Präsident und Max;;Hotel Nidum;Am Wiesenhang 1A;Mösern/Seefeld;6100;Österreich;;4,35E+13;;;;;info#nidum-hotel.com;P.;Aus;;2016
Especially the value 4,35E+13. Looks like a typical Excel/CSV conversion thing to me :)
I have a very simple test project where I am trying to figure out how to add children into the parent's collection.
The datamodel is quite basic:
Current result returns a duplicated entry.
Expected/desired
I expected the result to be just one entry with two children
GROUP1 -> { USER_1, USER_2 }
GROUP class
public class GROUP
{
public GROUP()
{
this.USERs = new HashSet<USER>();
}
public int Group_ID { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public ICollection<USER> USERs { get; set; }
}
USER class
public class USER
{
public int User_ID { get; set; }
public int Group_ID { get; set; }
public string Name { get; set; }
public Nullable<int> Age { get; set; }
public GROUP GROUP { get; set; }
}
Dapper method
public GROUP Get(int id)
{
string sqlGetGroupExtended = $"SELECT _group.Group_ID, _group.Name, _group.Location, _user.User_ID, _user.Name, _user.GROUP_ID, _user.Age FROM dbo.[GROUP] _group " +
"LEFT JOIN dbo.[USER] _user ON _group.Group_ID = _user.Group_ID " +
"WHERE _group.Group_ID = #groupid;";
GROUP result = null;
var lookup = new Dictionary<int, GROUP>();
using (var connection = new SqlConnection(Properties.Settings.Default.CodeTest_DB))
{
var extendedGroup = connection.Query<GROUP, USER, GROUP>(sqlGetGroupExtended, (parent, child) =>
{
if (!lookup.TryGetValue(parent.Group_ID, out GROUP found))
{
lookup.Add(parent.Group_ID, found = parent);
}
found.USERs.Add(child);
return found;
}, param: new { groupid = id }, splitOn: "Location");
// result = extendedGroup <--- WHAT TO DO HERE?
}
return result;
}
How can I achieve this?
References:
http://dapper-tutorial.net/dapper
https://github.com/StackExchange/Dapper/blob/master/Dapper.Tests/MultiMapTests.cs#L12
If you're using SQL Server 2016 or Azure SQL you can take advance of JSON to return a hierarchical object:
https://medium.com/dapper-net/one-to-many-mapping-with-dapper-55ae6a65cfd4
It's an article I wrote on the subject, along with source code, that shows how to elegantly solve the problem.
My bad, as the code shows here https://github.com/StackExchange/Dapper/blob/master/Dapper.Tests/MultiMapTests.cs#L12
I was missing the .Distinct()
var extendedGroup = connection.Query<GROUP, USER, GROUP>(sqlGetGroupExtended, (parent, child) =>
{
if (!lookup.TryGetValue(parent.Group_ID, out GROUP found))
{
lookup.Add(parent.Group_ID, found = parent);
}
found.USERs.Add(child);
return found;
}, param: new { groupid = id }, splitOn: "Location,User_ID").Distinct();
I'm trying to create an object and insert to the database but keep getting the same error no matter what I try.
The row that I get the error on is ColumnGroupTest.ValidValues.Add(memberComment1); the error is
error message
NullReferenceException was unhandled by user code
my models
public class StoreColumnName
{
public int Id { get; set; }
public string StoreColumnGroupName { get; set; }
public string ColumnName { get; set; }
public string ColumnType { get; set; }
public List<StoreValidValue> ValidValues { get; set; }
}
public class StoreValidValue
{
public int Id { get; set; }
public string ValidValue { get; set; }
public StoreColumnName StoreColumnName { get; set; }
}
my controller
public ActionResult Index()
{
XDocument document = XDocument.Load(#"C:\Users\Physical.xml");
var result = document.Descendants("ColumnGroup");
foreach(var item in result){
var ColumnGroupName = item.Attribute("name").Value;
var Columns = item.Descendants("Column");
foreach (var itemColumn in Columns)
{
StoreColumnName ColumnGroup = new StoreColumnName();
var ColumnGroupTest = new StoreColumnName
{
StoreColumnGroupName = ColumnGroupName,
ColumnName = itemColumn.Attribute("name").Value,
ColumnType = itemColumn.Attribute("type").Value,
Id = 11
};
var ValidValues = itemColumn.Descendants("ValidValues");
var Values = ValidValues.Descendants("Value");
foreach (var Value in Values)
{
var memberComment1 = new StoreValidValue
{
StoreColumnName = ColumnGroupTest,
ValidValue = Value.Value,
Id = 101
};
ColumnGroupTest.ValidValues.Add(memberComment1);
}
}
}
return View();
}
(I gladly take tips on what I can improve when asking for help/guiding here).
Can anyone help ?
The issue that you're having is that you don't initialize your ValidValues property to a list. By default, those types of properties initialize to null unless you specify differently.
The best approach is to add that initialization to your constructor of that object.
public StoreColumnName() {
this.ValidValues = new List<StoreValidValue>();
}
I wrote very simple class, that perfom data access.
It checks if line with that day exist in table and update her or create a new line.
public class DataAccessClass
{
public static DayWeather GetDayWeather(DateTime date)
{
try
{
using (var db = new Context())
{
var query =
(from day in db.DayWeather
where ((DateTime)day.DateOfDay).Date == date.Date
select new DayWeather((short)day.Temperature, (ushort)day.WindSpeed, (ushort)day.Pressure, (ushort)day.Humidity, day.Cloudiness, day.TypeRecip, (DateTime)day.DateOfDay)).First();
return query;
}
}
catch (Exception exp)
{
if (!EventLog.SourceExists("DataAccessSource"))
{
EventLog.CreateEventSource("DataAccessSource", "DataAccessErrorLog");
}
EventLog.WriteEntry("DataAccessSource", exp.Message);
throw new Exception("Problem with data get.");
}
}
public static void SaveDayWeather(DayWeather day)
{
try
{
using (var db = new Context())
{
var existingDay =
(from d in db.DayWeather
where ((DateTime)day.DateOfDay).Date == day.DateOfDay.Date
select d).SingleOrDefault<DayWeather>();
if (existingDay != null)
{
existingDay.Temperature = day.Temperature;
existingDay.WindSpeed = day.WindSpeed;
existingDay.Pressure = day.Pressure;
existingDay.Humidity = day.Humidity;
existingDay.Cloudiness = day.Cloudiness;
existingDay.TypeRecip = day.TypeRecip;
db.SaveChanges();
}
else
{
DayWeather newDay = new DayWeather();
newDay.DateOfDay = day.DateOfDay;
newDay.Temperature = day.Temperature;
newDay.WindSpeed = day.WindSpeed;
newDay.Pressure = day.Pressure;
newDay.Humidity = day.Humidity;
newDay.Cloudiness = day.Cloudiness;
newDay.TypeRecip = day.TypeRecip;
db.DayWeather.Add(newDay);
db.SaveChanges();
}
}
}
It use EF for generate database. The Contex class and class for save look like this:
public class DayWeather
{
public short Temperature { get; set; }
public ushort WindSpeed { get; set; }
public ushort Pressure { get; set; }
public ushort Humidity { get; set; }
public string Cloudiness { get; set; }
public string TypeRecip { get; set; }
public DateTime DateOfDay { get; set; }
public DayWeather(short Temperature, ushort WindSpeed, ushort Pressure, ushort Humidity, string Cloudiness, string TypeRecip, DateTime Date)
{
this.Temperature = Temperature;
this.WindSpeed = WindSpeed;
this.Pressure = Pressure;
this.Humidity = Humidity;
this.Cloudiness = Cloudiness;
this.TypeRecip = TypeRecip;
this.DateOfDay = Date;
}
public DayWeather()
{
}
}
internal class Context : DbContext
{
public DbSet<DayWeather> DayWeather { get; set; }
}
I call this methods by this code:
DataAccessClass.SaveDayWeather(new DayWeather(12, 12, 12, 12, "Yes", "rain", DateTime.Now));
DayWeather day = DataAccessClass.GetDayWeather(DateTime.Now);
Console.WriteLine(day.ToString());
Console.ReadKey();
It should generate new database, but error occurs. In message it write that can`t connect to the SQL Server.
Is somebody know what is wrong?
P.S. Sorry for my bad English.
P.P.S. I added EF by NuGet.
You can manually specify the connection string as follows
using (var db = new Context("connectionString"))
The default constructor looks up a connection string in the web.config with the same name as the derived context class Context.
If it fails to find one it defaults to
Data Source=.\SQLEXPRESS;
or
Data Source=(LocalDb)\v11.0;
depending on the version of sql server you are using.
I'm fetching information from a webpage in two pages:
First page:
- Content c1 is created and a Translation c1.t1 is created;
- Content c2 is created and Translation c2.t1 is created;
Second page:
- The system detects that c1 already exists and just adds c1.t2 to the proper table;
- The system detects that c2 already exists and just adds c2.t2 to the proper table;
Somehow, on the second page, the system is overritting c1.t1 with c1.t2 and only the second translation is available on the database. When debbugging, found that it is deletting c1.t1 at some point but I couldn't figure out why.
This is my actual stuff:
EF 4.1
Code-First Aproach
DbContext
I have this POCO Entities (minimized):
RegionalContent: - It's like a tranlation and regional info about a content:
public class XBLRegionalContent
{
[Key, Column(Order = 0)]
public string ContentId { get; set; }
[ForeignKey("ContentId")]
public virtual XBLContent Content { get; set; }
[Key, Column(Order = 1)]
public string RegionId { get; set; }
[ForeignKey("RegionId")]
public virtual XBLRegion Region { get; set; }
public string Name { get; set; }
}
Content: - Unique content per GUID:
public class XBLContent
{
#region [ Properties ]
/// <summary>
/// The GUID
/// </summary>
[Key]
[StringLength(36, ErrorMessage="Must have 36 characters")]
[Required(ErrorMessage="Must have a unique GUID")]
public string GUID { get; set; }
public string Type { get; set; }
public virtual ICollection<XBLRegionalContent> RegionalInfo { get; set; }
}
Region - Pretty straight forward:
public class XBLRegion
{
[Key]
[StringLength(5, ErrorMessage="ID must have 5 characters")]
[Required]
[RegularExpression(#"[a-z]{2}-[A-Z]{2}", ErrorMessage = "ID must be in ISO 639 standard")]
public string ID { get; set; }
public string Country { get; set; }
public string Language { get; set; }
}
DbContext class has nothing different, just DbSets.
One content has many translations. One translation has one content related. The translation primary key is compound of content guid and region id.
I have a class in Model that populates the database and creates a local list that the View uses to display information. That way, I only access the Database one time to save, and don't need to retrieve information when it is saved.
Here is only the important information about this class:
public class XBLChart : IDisposable
{
XBLContentContext db = new XBLContentContext();
private string baseurl = "http://foo.bar/";
public string Locale { get; private set; }
public string HTML { get; private set; }
public string URL { get; set; }
public ContentType Type { get; private set; }
public List<XBLContent> Contents { get; set; }
public XBLChart(ContentType type, string sort, string locale)
{
Type = type;
if (sort == null)
sort = Enum.GetName(typeof(SortBy), SortBy.OfferStartDate);
if (locale != null && locale.Length == 5)
Locale = locale;
else
Locale = "en-US";
URL = baseurl + Locale + "/" + sort;
HTML = FeedUtils.RequestHTML(URL);
Contents = new List<XBLContent>();
PopulateList();
}
private void PopulateList()
{
MatchCollection itens = Regexes.ChartItems().Matches(HTML);
MatchCollection titulos = Regexes.ChartTitles().Matches(HTML);
int type = (int)Type;
int start = type * 12;
this.Title = HttpUtility.HtmlDecode(titulos[type].Groups["title"].Value);
if (titulos.Count < 8 && start > 1)
{
start = (type - 1) * 12;
type--;
}
XBLRegion region;
if (!db.XBLRegions.Any(x => x.ID == Locale))
{
region = new XBLRegion { ID = Locale };
db.XBLRegions.Add(region);
db.SaveChanges();
}
else
region = db.XBLRegions.SingleOrDefault(x => x.ID == Locale);
for (int i = start; i < (start + 2); i++)
{
string guid = itens[i].Groups["guid"].Value;
XBLContent c = new XBLContent(guid);
if (!db.XBLContents.Any(x => x.GUID == guid))
{
c.Type = Type.ToString();
c.PopularInfo(Locale);
db.XBLContents.Add(c);
}
else
c = db.XBLContents.Single(x => x.GUID == c.GUID);
XBLRegionalContent regionalcontent = new XBLRegionalContent(guid, Locale);
if (!db.XBLRegionalInfos.Any(x => x.ContentId == guid && x.RegionId == Locale))
{
if (c.HTML == null)
c.PopularInfo(Locale);
regionalcontent.Populate(c.HTML);
regionalcontent.Name = HttpUtility.HtmlDecode(itens[i].Groups["name"].Value);
db.XBLRegionalInfos.Add(regionalcontent);
}
else
regionalcontent = db.XBLRegionalInfos.Single(x => x.ContentId == guid && x.RegionId == Locale);
db.SaveChanges();
c.RegionalInfo.Clear();
regionalcontent.Region = region;
c.RegionalInfo.Add(regionalcontent);
Contents.Add(c);
}
}
}
you are missing a db.SaveChanges() after
db.SaveChanges();
c.RegionalInfo.Clear();
regionalcontent.Region = region;
c.RegionalInfo.Add(regionalcontent);