Simplest way to populate class from query in C# [closed] - c#

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 7 years ago.
Improve this question
I want to populate a class from a query.
this is an example class:
private class TVChannelObject
{
public string number { get; set; }
public string title { get; set; }
public string favoriteChannel { get; set; }
public string description { get; set; }
public string packageid { get; set; }
public string format { get; set; }
}
How can I fill this class from an database query? Is there any way to do this automatically as far as table column names are identical to class attributes?

As others have suggested, an ORM is the best way to go. You could, however, implement this functionality using reflection:
using System.Reflection;
void Main()
{
var connectionString = "...";
var records = new Query(connectionString).SqlQuery<TVChannel>("select top 10 * from TVChannel");
}
private class TVChannel
{
public string number { get; set; }
public string title { get; set; }
public string favoriteChannel { get; set; }
public string description { get; set; }
public string packageid { get; set; }
public string format { get; set; }
}
public class Query
{
private readonly string _connectionString;
public Query(string connectionString)
{
_connectionString = connectionString;
}
public List<T> SqlQuery<T>(string query)
{
var result = new List<T>();
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = query;
using (var reader = command.ExecuteReader())
{
var columns = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToArray();
var properties = typeof(T).GetProperties();
while (reader.Read())
{
var data = new object[reader.FieldCount];
reader.GetValues(data);
var instance = (T)Activator.CreateInstance(typeof(T));
for (var i = 0; i < data.Length; ++i)
{
if (data[i] == DBNull.Value)
{
data[i] = null;
}
var property = properties.SingleOrDefault(x => x.Name.Equals(columns[i], StringComparison.InvariantCultureIgnoreCase));
if (property != null)
{
property.SetValue(instance, Convert.ChangeType(data[i], property.PropertyType));
}
}
result.Add(instance);
}
}
}
}
return result;
}
}

You can use Linq to SQL with C#. With Linq, you can easily map your tables with C# classes and then query or populate them with a few lines of code.
Check out this link: Insert rows with Linq to SQL
EDIT:
The first thing you need to do is to map your class to your database table. Like this:
[Table(Name = "tvchannel")] // Here you put the name of the table in your database.
private class TVChannelObject
{
Column(Name = "number", IsPrimaryKey = true)] // Here, number is the name of the column in the database and it is the primary key of the table.
public string number { get; set; }
[Column(Name = "title", CanBeNull = true)] // If the field is nullable, then you can set it on CanBeNull property.
public string title { get; set; }
[Column(Name = "channelFavorite", CanBeNull = true)] // Note that you can have a field in the table with a different name than the property in your class.
public string favoriteChannel { get; set; }
[Column(Name = "desc", CanBeNull = true)]
public string description { get; set; }
[Column(Name = "package", CanBeNull = false)]
public string packageid { get; set; }
[Column(Name = "format", CanBeNull = false)]
public string format { get; set; }
}
After mapping your database with the corresponding fields for your table, you can now build a method in your class to insert a row:
public void InsertTvChannel()
{
// DataContext takes a connection string.
string connString = "Data Source=SomeServer;Initial Catalog=SomeDB;User ID=joe;Password=swordfish" //example
DataContext db = new DataContext(connString);
// Create a new object tv channel to insert
TVChannelObject channel = new TVChannelObject();
channel.number = 1;
channel.title = "Some title";
channel.favoriteChannel = "some channel";
channel.description = "some description";
channel.packageid = "the package id";
channel.format = "the format";
// Now that you have the object for the new channel, let's insert it:
db.TVChannelObjects.InsertOnSubmit(channel); //this just adds to a collection. It is a prepare to insert.
// Submit the change to the database.
try
{
db.SubmitChanges();
}
catch (Exception e)
{
Console.WriteLine(e);
// If you face errors, you can handle it with some code here.
// ...
// Try again.
db.SubmitChanges();
}
}
This code should work, with just a few adjustments. Now you have an example to insert with a Linq mapping.

Use ORM like entity framework.
For your simplicity , follow this link
www.codeproject.com/Articles/739164/Entity-Framework-Tutorial-for-Beginners

Related

Is this a good way to set more properties value after query?

This is what I do to set more properties value after query. Please see the method GetMoreData(), it will be executed for every detail loop and starts causing performance issue.
Is there a better way of doing this? I know the class constuctor that execute during object instantiate. But in this case, more properites must be set after database query.
Note: This is a cut-down version of source code focusing on important part only, please accept typo error, if any.
public class OrderHeader
{
// Real database column
public string OrderId { get; set; }
public string ColA { get; set; }
public string ColB { get; set; }
public string PostCode { get; set; }
public decimal TotalWeight { get; set; }
public decimal TotalShipmentFee { get; set; }
}
public class OrderDetail
{
// Real database column
public string OrderId { get; set; }
public string OrderLine { get; set; }
public decimal Weight { get; set; }
public decimal ShipmentFee { get; set; }
// mock-up column for displaly only, not exist in datababse
public string ColA { get; set; }
public string ColB { get; set; }
}
public static List<OrderDetail> GetByItemClass(string itemClass)
{
using (IDbConnection db = new MySqlConnection(connectionStringGoesHere)) {
string sqlCmd = #"SELECT * FROM orderdetail WHERE ItemClass = #ItemClass";
List<OrderDetail> orderDetails = db.Query<OrderDetail>(sqlCmd, new {
#ItemClass = itemClass
}).ToList();
// Get or build or calculate additional properties
for (int i = 0; i < orderDetails.Count; i++) {
orderDetails[i] = GetMoreData(orderDetails);
}
return orderDetails;
}
}
public static List<OrderDetail> GetByItemType(string itemType)
{
using (IDbConnection db = new MySqlConnection(connectionStringGoesHere)) {
string sqlCmd = #"SELECT * FROM orderdetail WHERE ItemType = #ItemType";
List<OrderDetail> orderDetails = db.Query<OrderDetail>(sqlCmd, new {
#ItemType = itemType
}).ToList();
// Get or build or calculate additional properties
for (int i = 0; i < orderDetails.Count; i++) {
orderDetails[i] = GetMoreData(orderDetails);
}
return orderDetails;
}
}
public static OrderDetail GetMoreData(OrderDetail orderDetail)
{
// Performance problem: Need to query order header for every
// single loop even multiple records having the same OrderId
OrderHeader orderHeader = OrderHeaderDal.GetById(orderDetail.OrderId);
// Directly map value
orderDetail.ColA = orderHeader.ColA;
orderDetail.ColB = orderHeader.ColB;
// Calculate value
if (orderHeader.PostCode == "0") {
orderDetail.ShipmentFee = orderDetail.Weight * 1.15;
// More complex to get value from another table
} else {
// Might also cause performance issue for many query loop
Rate rate = RateDal.GetByPostCode(orderHeader.PostCode);
orderDetail.ShipmentFee = orderDetail.Weight * rate.RatePerKg;
}
return orderDetail;
}

Parse XML with Linq with multiple child elements

This is my first question on SO, please let me know if I am doing anything wrong!
I am trying to parse an XML similar to this:
<LiveUpdate>
<CityID>F0A21EA2</CityID>
<CityName>CityTown</CityName>
<UserName>john</UserName>
<ApplicationDetails>
<ApplicationDetail
Application="AC"
Licensed="true"
Version="2015.2"
Patch="0001"
/>
<ApplicationDetail
Application="AP"
Licensed="true"
Version="2015.2"
Patch="0002"
/>
</ApplicationDetails>
</LiveUpdate>
I have classes that look like this:
public class Client
{
public string cityID { get; set; }
public string cityName { get; set; }
public string userName { get; set; }
public List<Apps> appList { get; set; }
}
public class Apps
{
public string app { get; set; }
public string licensed { get; set; }
public string version { get; set; }
public string patch { get; set; }
}
I need to be able to have a client class with a list of all the application details to be iterated over.
So far the best I've come up with is:
XDocument xml = XDocument.Load(#"C:\blah\Desktop\1.xml");
var liveUpdate = xml.Root;
var clients = (from e in liveUpdate.Elements()
select new Client()
{
cityID = e.Element("CityID").Value,
cityName = e.Element("CityName").Value,
userName = e.Element("UserName").Value,
appList = e.Elements("ApplicationDetails")
.Select(a => new Apps()
{
app = a.Element("Application").Value,
licensed = a.Element("Licensed").Value,
version = a.Element("Version").Value,
patch = a.Element("Patch").Value
}).ToList()
});
However, I'm currently running into an error that says Object reference not set to an instance of an object.
I've seen some similar examples on here, but not that deal with data before the multiple children.
I'm fairly new to XML and Linq so any help here would be greatly appreciated!
Your XML only contains one LiveUpdate tag, so rather than iterating over all of the elements inside of it, you just want to look at the Root element.
In ApplicationDetails, Application, Licensed and such are attributes, not elements. Use .Attribute() to access them.
ApplicationDetails is a single tag, and inside it you have ApplicationDetail tags.
There is no DateTime element in your LiveUpdate tag.
This works:
var liveUpdate = xml.Root;
var e = liveUpdate;
var clients = new Client()
{
cityID = e.Element("CityID").Value,
cityName = e.Element("CityName").Value,
userName = e.Element("UserName").Value,
//dateTime = e.Element("DateTime").Value,
appList = e.Element("ApplicationDetails").Elements("ApplicationDetail")
.Select(a => new Apps()
{
app = a.Attribute("Application").Value,
licensed = a.Attribute("Licensed").Value,
version = a.Attribute("Version").Value,
patch = a.Attribute("Patch").Value
}).ToList()
};
Since you have already defined a class into which you wish to deserialize, you can use XmlSerializer to deserialize it for you.
First, let's rename some of your property names to more closely match the XML and c# naming conventions:
[XmlRoot("LiveUpdate")]
public class Client
{
public string CityID { get; set; }
public string CityName { get; set; }
public string UserName { get; set; }
[XmlArray("ApplicationDetails")]
[XmlArrayItem("ApplicationDetail")]
public List<Apps> AppList { get; set; }
}
public class Apps
{
[XmlAttribute]
public string Application { get; set; }
[XmlAttribute]
public bool Licensed { get; set; }
[XmlAttribute]
public string Version { get; set; }
[XmlAttribute]
public string Patch { get; set; }
}
Then add the following extension methods:
public static class XmlSerializationHelper
{
public static T LoadFromXML<T>(this string xmlString)
{
using (StringReader reader = new StringReader(xmlString))
{
object result = new XmlSerializer(typeof(T)).Deserialize(reader);
if (result is T)
{
return (T)result;
}
}
return default(T);
}
public static T LoadFromFile<T>(string filename)
{
using (var fs = new FileStream(filename, FileMode.Open))
{
object result = new XmlSerializer(typeof(T)).Deserialize(fs);
if (result is T)
{
return (T)result;
}
}
return default(T);
}
}
Now you can deserialize from your XML file as follows:
string fileName = #"C:\blah\Desktop\1.xml";
var client = XmlSerializationHelper.LoadFromFile<Client>(fileName);
I manually updated your Client class to map correctly to the provided XML, but if you wanted to do it automatically, see here: Generate C# class from XML.

How to insert data from MS Access to SQL after checking whether the data exists or not in the database using Entity Framework

Hopefully, the question header is clear enough to tell that I'm trying to read an Access file and upload the data to the database but checking at first whether the data already exists or not in the database.
I receive a daily report from a third-party company in Access file. I'm trying to create a windows service that will check for the file every morning, and if the new file exist, then it'll read and upload the data to the database. I'm trying to use Entity Framework. I read the article on Navigation Property, but I'm still confused on that; I never used navigation property before. Here are my models:
[Table("ClaimsTable")]
public partial class ClaimsTable
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int ClaimsID { get; set; }
public string EOPAID { get; set; }
public string AuthID { get; set; }
public string PAStatus { get; set; }
public string UserName { get; set; }
[DataType(DataType.Date)]
public DateTime EffectiveDate { get; set; }
[DataType(DataType.Date)]
public DateTime EndDate { get; set; }
public string RecordType { get; set; }
public int RxID { get; set; }
public int MemberID { get; set; }
public int PrescriberID { get; set; }
public string EditNumber { get; set; }
public string OriginSource { get; set; }
public string OriginMethod { get; set; }
/*
[ForeignKey("RxID")]
public virtual RxTable Prescription { get; set; }
[ForeignKey("MemberID")]
public virtual MembersTable Member { get; set; }
[ForeignKey("PrescriberID")]
public virtual PrescribersTable Prescriber { get; set; }
*/
}
...
[Table("MembersTable")]
public partial class MembersTable
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int MemberID { get; set; }
[DataType(DataType.Date), Display(Name= "Date of Birth"), DisplayFormat(DataFormatString="{0:mm/dd/yyyy}", ApplyFormatInEditMode=true)]
public DateTime DateofBirth { get; set; }
public string CardholderID { get; set; }
public string MemberFirstName { get; set; }
public string MemberLastName { get; set; }
//public virtual ICollection<AddressTable> Address { get; set; }
}
...
[Table("PrescribersTable")]
public partial class PrescribersTable
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int PrescriberID { get; set; }
public string NPI { get; set; }
public string PrescriberFirstName { get; set; }
public string PrescriberLastName { get; set; }
public string PhysicianType { get; set; }
//public ICollection<AddressTable> Address { get; set; }
}
....
using(OleDbConnection conn = new OleDbConnection(strDSN))
{
OleDbDataReader reader = null;
OleDbCommand command = new OleDbCommand("Select * from table", conn);
try
{
conn.Open();
}
catch(OleDbException o)
{
return o.Message;
}
reader = command.ExecuteReader();
List<ClaimsTable> Claim = new List<ClaimsTable>();
List<PrescribersTable> PrescriberInDB = new List<PrescribersTable>();
List<MembersTable> MembersInDB = new List<MembersTable>();
while(reader.Read())
{
PrescriberInDB = context.Prescribers.ToList();
MembersInDB = context.Members.ToList();
//CREATE LOCAL VARIABLE
string recordType = //check if the member and the prescriber exist in the database
int prescriberID = 0;
int prodID = 0;
int memberID = 0;
int drugID = 0;
int RxID = 0;
int claimID = 0;
//check if the member and the prescriber exist in the object before inserted into the database.
//the data will be uploaded to the database in bulk
//int newPrescriberID = Prescriber.Where(x => x.PrescriberFirstName == reader["Prescriber First Name"] && x.PrescriberLastName == reader["Prescriber Last Name"] && x.NPI == reader["Prescribing Physician"]).Select(x => x.PrescriberID).FirstOrDefault();
//int newMemberID = Member.Where(x => x.MemberFirstName == reader["Member First Name"] && x.MemberLastName == reader["Member Last Name"] && x.CardholderID == reader["CardhHolder"]).Select(x => x.MemberID).FirstOrDefault();
//insert the data if it doesn't exist
if(!PresciberExist(prescriberFirstName, prescriberLastName, npi, PrescriberInDB))
{
var prescriber = new PrescribersTable()
{
PrescriberFirstName = prescriberFirstName,
PrescriberLastName = prescriberLastName,
NPI = npi,
PhysicianType = physicianType
};
context.Prescribers.Add(prescriber);
context.SaveChanges();
prescriberID = GetPrescriberID(prescriberFirstName, prescriberLastName, physicianType, PrescriberInDB);
}
if(!MemberExist(memberFirstName, memberLastName, cardholderID, MembersInDB))
{
var member = new MembersTable()
{
MemberFirstName = memberFirstName,
MemberLastName = memberLastName,
CardholderID = cardholderID,
DateofBirth = dob
};
context.Members.Add(member);
context.SaveChanges();
memberID = GetMemberID(memberFirstName, memberLastName, cardholderID, MembersInDB);
}
}
}
return "Done uploading";
}
private bool MemberExist(string memberFirstName, string memberLastName, string cardholderID, List<MembersTable> MembersInDB)
{
return MembersInDB.Exists(x => x.MemberFirstName == memberFirstName && x.MemberLastName == memberLastName && x.CardholderID == cardholderID);
}
private bool PresciberExist(string prescriberFirstName, string prescriberLastName, string npi, List<PrescribersTable> PrescriberInDB)
{
return PrescriberInDB.Exists(x => x.PrescriberFirstName == prescriberFirstName && x.PrescriberLastName == prescriberLastName && x.NPI == npi);
}
The access database contains sensitive information, so I won't be able to add those data as an example. But here's a made up data for test. The data contains claims of patients.
Now, because there are many drugs and many claims for the same patient, and many patients for a prescriber.. I broke the database as it's shown above. Needs improvement? I welcome suggestion. The reason I did this is because I don't want my database to have repeated records which will make managing really troubling. This way, I'll have unique members in memberstable, unique prescribers in prescriberstable and so on and so forth.
The challenge I'm facing is that when I read the data from the access database, I'm assuming it reads row-wise. The code should first check the database whether the member exist or not. If it does, then get the member id which is an identity column. If it doesn't, then it should insert the member's info only, and then get the memberID. Similarly, I do the same thing with the prescriber's data. Check and insert if needed. This is the long way, and this is the only way I could figure out how to do it.
I know this is not a very good programming. I'm just an analyst who unfortunately has to do a lot of programming. And I'm learning as I go. With that said, there's a lot of ways to improve this code - I just don't know any. Can you point me to the right direction? Also, an example of how to check and insert the data if it doesn't exist in the database using navigation property. Currently, the data is read and uploaded just fine, but I saw in the database that it didn't quite do what I wanted it to do. It still added a couple of already existing members. I seriously needs some help.

Pass widget data using json and saving to database

I have just come back to this requirement again as I was pulled away from it to do more important requirements at the time.
I have asked a similar question here and the answer has helped. However, in that question, I was passing test data and saving it to the database. I'm unable to figure out how to save the actual widget information however. The link helped me with passing the json successfully.
I receive this message when trying to save the data.
jQuery
function updateWidgetData() {
var items = [];
$('.column').each(function () {
var columnId = $(this).attr('id');
$('.dragbox', this).each(function (i) {
var collapsed = 0;
if ($(this).find('.dragbox-content').css('display') == "none")
collapsed = 1;
//Create Item object for current panel
var item = {
id: $(this).attr('id'),
collapsed: collapsed,
order: i,
column: columnId
};
//Push item object into items array
items.push(item);
});
});
//Assign items array to sortorder JSON variable
var sortorder = { items: items };
$.ajax({
url: "/Handlers/SaveWidgets.ashx",
type: "POST",
contentType: "application/json; charset=uft-8",
dataType: "json",
data: JSON.stringify(sortorder),
success: function (response) {
alert("Passed json");
},
error: function (error) {
alert("Failed passing json.");
}
});
Handler
public void ProcessRequest(HttpContext context)
{
String json = String.Empty;
// you have sent JSON to the server
// read it into a string via the input stream
using (StreamReader rd = new StreamReader(context.Request.InputStream))
{
json = rd.ReadToEnd();
}
// create an instance of YourDataModel from the
// json sent to this handler
SaveWidgetsDAL data = null;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(SaveWidgetsDAL));
using (MemoryStream ms = new MemoryStream())
{
byte[] utf8Bytes = Encoding.UTF8.GetBytes(json);
ms.Write(utf8Bytes, 0, utf8Bytes.Length);
ms.Position = 0;
data = serializer.ReadObject(ms) as SaveWidgetsDAL;
}
// update the DB and
// send back a JSON response
int rowsUpdated = 0;
foreach (var item in data.wdata)
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["dboCao"].ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("UPDATE tWidgetControl SET SortNo = #SortNo, ColumnId = #ColumnId, Collapsed = #Collapsed "
+ "WHERE UserId = #UserId AND WidgetId = #WidgetId;", conn))
{
cmd.Parameters.AddWithValue("#SortNo", item.SortNo);
cmd.Parameters.AddWithValue("#ColumnId", item.ColumnId);
cmd.Parameters.AddWithValue("#Collapsed", item.Collapsed);
cmd.Parameters.AddWithValue("#UserId", "2");
cmd.Parameters.AddWithValue("#WidgetId", item.WidgetId);
rowsUpdated = cmd.ExecuteNonQuery();
}
conn.Close();
}
}
context.Response.ContentType = "application/json";
context.Response.Write("{ \"rows_updated\": " + rowsUpdated + " }");
}
public bool IsReusable
{
get
{
return false;
}
}
Widgets Data Class
public class SaveWidgetsDAL
{
public List<Widgets> wdata { get; set; }
public SaveWidgetsDAL() { }
public class Widgets
{
[DataMember]
public string SortNo { get; set; }
[DataMember]
public string ColumnId { get; set; }
[DataMember]
public string Collapsed { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string UserId { get; set; }
[DataMember]
public string WidgetId { get; set; }
}
}
I would imagine that I would need to save the json into a list and then insert/update each widget information into the database. However, I receive the error above when I try this. I'm clearly missing something, but I am not sure what it is. This error occurs in my handler, but the list in the SaveWidgetsDAL is empty, causing the NullReference. I am not sure what I am missing or sure where to go from here. Any help is greatly appreciated!
EDIT 1:
I have changed my database around a bit along with my SaveWidgetsDAL.
SaveWidgetsDAL
[DataContract]
public class SaveWidgetsDAL
{
[DataMember(Name = "items")]
public List<Widgets> wdata { get; set; }
public SaveWidgetsDAL() { }
public class Widgets
{
[DataMember(Name = "order")]
public string SortNo { get; set; }
[DataMember(Name = "column")]
public string ColumnId { get; set; }
[DataMember(Name = "collapsed")]
public string Collapsed { get; set; }
[DataMember(Name = "id")]
public string Title { get; set; }
}
}
Handler (just the foreach)
foreach (var item in data.wdata)
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["dboCao"].ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("UPDATE tWidgetTest SET Title = #Title, SortNo = #SortNo, ColumnId = #ColumnId, Collapsed = #Collapsed "
+ "WHERE UserId = #UserId AND Title = #Title;", conn))
{
cmd.Parameters.AddWithValue("#Title", item.Title);
cmd.Parameters.AddWithValue("#SortNo", item.SortNo);
cmd.Parameters.AddWithValue("#ColumnId", item.ColumnId);
cmd.Parameters.AddWithValue("#Collapsed", item.Collapsed);
cmd.Parameters.AddWithValue("#UserId", "2");
rowsUpdated = cmd.ExecuteNonQuery();
}
conn.Close();
}
}
However, I now get this error when inserting into the database.
I'm able to see that my foreach count is 11, but the Collapsed, SortNo, ColumnId, Title are all null for each item.
The problem seems to be that the data member names specified in your c# data contract do not match the JSON property names in the JSON you are generating. Your JavaScript code generates JSON that looks like
{"items":[{"id":"1","collapsed":"False","order":"1","column":"1"}]}
But these property names are not the property names in your c# classes, and you have not overridden those names. Try something like the following instead:
[DataContract]
public class SaveWidgetsDAL
{
[DataMember(Name="items")]
public List<Widgets> wdata { get; set; }
public SaveWidgetsDAL() { }
[DataContract]
public class Widgets
{
// I was able to figure out which JSON properties to which to map these properties.
[DataMember(Name = "column")]
public string ColumnId { get; set; }
[DataMember(Name = "collapsed")]
public string Collapsed { get; set; }
// However it is unclear how to map these to your JSON.
[DataMember(Name = "sortno")]
public string SortNo { get; set; }
[DataMember(Name = "title")]
public string Title { get; set; }
[DataMember(Name = "userid")]
public string UserId { get; set; }
[DataMember(Name = "widgetid")]
public string WidgetId { get; set; }
}
}
I was able to deduce the correct c# data member names for collapsed: collapsed and column: columnId, however I could not figure out how to map the rest since they don't seem to match up 1-1. You will need to further fix the data member names to make them match exactly.
Update2
In your updated question, you omitted the [DataContract] attribute on the nested Widgets class:
// [DataContract] missing
public class Widgets
{
You need to make sure both the outer and nested classes have this attribute.
Update
This is the part of your code that creates your JSON:
var collapsed = 0;
if ($(this).find('.dragbox-content').css('display') == "none")
collapsed = 1;
//Create Item object for current panel
var item = {
id: $(this).attr('id'),
collapsed: collapsed,
order: i,
column: columnId
};
//Push item object into items array
items.push(item);
var json = JSON.stringify(sortorder);
Thus each object item in your items array contains just these four named properties:
id
collapsed
order
column
The property names you use in your var item = { id: value1, collapsed: value2, ...}; statement are the names that JSON.stringify() writes into the json string. The data member names specified in your c# code must match these names exactly in order to deserialize them with DataContractJsonSerializer. Thus the following c# classes will deserialize those four named properties:
[DataContract]
public class SaveWidgetsDAL
{
[DataMember(Name = "items")]
public List<Widgets> wdata { get; set; }
public SaveWidgetsDAL() { }
[DataContract]
public class Widgets
{
// I was able to figure out which JSON properties to which to map these properties.
[DataMember(Name = "id")]
public string Id { get; set; }
[DataMember(Name = "collapsed")]
public string Collapsed { get; set; }
[DataMember(Name = "order")]
public string Order { get; set; }
[DataMember(Name = "column")]
public string ColumnId { get; set; }
}
}
If you need to transfer additional properties, you need to add them in your var item statement, then add properties with the identical data member name in your Widgets class. To confirm you have correctly matched the names, you can either debug your ProcessRequest() method with Visual Studio and manually examine your json string, or debug log your json string via:
System.Diagnostics.Debug.WriteLine(json);
That will allow you to see the JSON and ensure that your data member names match your JSON property names.

Error inserting record with entity framework

I am sorry if it has already been answered but I can't find any solution. Here is my (little) problem. Also all my apologies if the terms I use are approximate, I am far from being a skilled C# developer
Note that I think my problem is similar to this one Entity Framework validation error for missing field, but it's not missing?
I have a table "Tweets" with a tweet_id field (bigint) which is my primary key.
I use the following class to load the table :
class TwitterDbContext : DbContext
{
public TwitterDbContext() : base("Twitter")
{
}
public DbSet<Stream> Streams { get; set; }
public DbSet<StreamParameter> StreamParameters { get; set; }
public DbSet<Tweet> Tweets { get; set; }
}
public class Tweet
{
public Tweet()
{
}
[Key]
public long tweet_id { get; set; }
public string tweet { get; set; }
public long creator { get; set; }
public double latitude { get; set; }
public double longitude { get; set; }
public string language { get; set; }
public DateTime created_at { get; set; }
public DateTime registered_at { get; set; }
public long? in_reply_to { get; set; }
public bool retweeted { get; set; }
}
I have an other class to store within the code execution all the fields used by the Tweet table. For the need here, let's imagine I manually create it that way
private void Test_Button_Click(object sender, RoutedEventArgs e)
{
Twts twtReceived = new Twts();
twtReceived.tweet_id = 1;
twtReceived.tweet = "test";
twtReceived.creator = 1;
twtReceived.latitude = -1;
twtReceived.longitude = -1;
twtReceived.language = "a";
twtReceived.created_at = DateTime.Now;
twtReceived.registered_at = DateTime.Now;
twtReceived.in_reply_to = 1;
twtReceived.retweeted = true;
AddTweet(twtReceived);
}
Now here is the AddTweet method
static public void AddTweet(Twts twtReceived)
{
try
{
// update the tweet data in the database
using (var TwitterDb = new TwitterDbContext())
{
Tweet twt = new Tweet()
{
tweet_id = twtReceived.tweet_id,
tweet = twtReceived.tweet,
creator = twtReceived.creator,
longitude = twtReceived.longitude,
latitude = twtReceived.latitude,
language = twtReceived.language,
created_at = twtReceived.created_at,
registered_at = twtReceived.registered_at,
in_reply_to = twtReceived.in_reply_to,
retweeted = twtReceived.retweeted
};
TwitterDb.Tweets.Add(twt);
TwitterDb.SaveChanges();
}
}
catch(Exception ex)
{
MessageBox.Show(ex.InnerException.ToString());
}
}
I constantly have the same error message:
Cannot insert the value NULL into column 'tweet_id', table
'Twitter.dbo.Tweets'; column does not allow nulls. INSERT fails.
The thing is that when I spy on "TwitterDb.Tweets.Local" after TwitterDb.Tweets.Add(twt); I correctly have tweet_id set to 1.
Any idea where is the issue?
Try marking your tweet_id field with following (instead of just [Key]), if this is a primary key column where you want to provide values yourself
[Required, Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
If it is an auto-increment, then remove explicit assignments to this field and mark it as 'Identity' instead:
[Required, Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]

Categories

Resources