I am designing a simple db. Two tables were quite similar so I've used inheritance mapping technique.
[Table]
[InheritanceMapping(Code = "P", Type = typeof(ATable),
IsDefault = true)]
[InheritanceMapping(Code = "E", Type = typeof(BTable))]
public class ATable: TableBase
{
[Column(IsDiscriminator = true)]
public string DiscKey;
private int _Id;
[Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
public int Id
{
get { return _Id; }
set
{
if (_Id != value)
{
NotifyPropertyChanging("Id");
_Id = value;
NotifyPropertyChanged("Id");
}
}
}
....
}
public class BTable : ATable
{
private int _Property;
[Column]
public int Property
{
get { return _Property; }
set
{
if (_Property!= value)
{
NotifyPropertyChanging("Property");
_DeviceDetailsId = value;
NotifyPropertyChanged("Property");
}
}
}
...
}
//DBDATACONTEXT
public class DBDataContext : DataContext
{
public DBDataContext(string connectionString) : base(connectionString) {}
public Table<ATable> As;
}
when I try:
var db = DBDataContext("Data Source=isostore:/xDB.sdf;Password='testpass';");
var atable = new ATable();
db.As.InsertOnSubmit(atable);
db.SubmitChanges();
I get an exception: The column cannot contain null values. [ Column name = Property,Table name = ATable]
What's wrong?!
The row on the table will always contains all the properties of all the inherited entities... so marking child columns(properties) with CanBeNull = true will solve the problem.
Related
I want to serialize Dictionary<long, VALUE> to following JSON in MongoDB.
{
"213" : {},
"63624" : {},
...
}
I don't want other DictionaryRepresentation except DictionaryRepresentation.Document.Document
I am using MongoDB C# Driver (v2.0.1.27), and it is not smart to convert the long type key into string, which causes an exception.
You can do this with the existing serializers but it requires a small amount of configuration.
Assume the following class:
public class C
{
public int Id { get; set; }
public Dictionary<long, long> D { get; set; }
}
You can configure a custom serializer for the D property (the Dictionary) that uses a key serializer that serializes longs to strings. The code would look like this:
BsonClassMap.RegisterClassMap<C>(cm =>
{
cm.AutoMap();
var customDictionarySerializer = new DictionaryInterfaceImplementerSerializer<Dictionary<long, long>>(
dictionaryRepresentation: DictionaryRepresentation.Document,
keySerializer: new Int64Serializer(BsonType.String),
valueSerializer: BsonSerializer.SerializerRegistry.GetSerializer<long>());
cm.GetMemberMap(c => c.D).SetSerializer(customDictionarySerializer);
});
The key idea here is that even though the keys and values are both longs, we are using different serializers for the keys and the values.
If we then run a quick test:
var document = new C { Id = 1, D = new Dictionary<long, long> { { 2, 3 } } };
var json = document.ToJson();
Console.WriteLine(json);
We see that the Dictionary keys are now being serialized as strings:
{ "_id" : 1, "D" : { "2" : NumberLong(3) } }
Also I worked out another solution, hope it helps other people
public class LongDictionarySerializer<K> : DictionarySerializerBase<Dictionary<long, K>>
{
public LongDictionarySerializer() : base(DictionaryRepresentation.Document)
{
}
protected override Dictionary<long, K> CreateInstance()
{
return new Dictionary<long, K>();
}
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Dictionary<long, K> value)
{
if (value != null)
{
Dictionary<string, K> dic = value.ToDictionary(d => d.Key.ToString(), d => d.Value);
BsonSerializer.Serialize<Dictionary<string, K>>(context.Writer, dic);
}
else
BsonSerializer.Serialize<object>(context.Writer, null);
}
public override Dictionary<long, K> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
Dictionary<string, K> dic = BsonSerializer.Deserialize<Dictionary<string, K>>(context.Reader);
if (dic == null)
return null;
Dictionary<long, K> ret = new Dictionary<long, K>();
foreach( var pair in dic )
{
long key;
if (!long.TryParse(pair.Key, out key))
continue;
ret[key] = pair.Value;
}
return ret;
}
}
Then on the field
[BsonElement(Fields.Markets)]
[BsonSerializer(typeof(LongDictionarySerializer<XXX>))]
public Dictionary<long, XXX> Markets { get; set; }
I get this error:
Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 251: ManageAccount.Instance.GetUserAccounts(username), "accountID", "name", accountFrom);
Line 252:
Line 253: Currencies = new SelectList(
Line 254: ManageCurrency.Instance.getCurrencies(), "id", "name",_Account.currency1.id);
Line 255:
It gives the error in this viewModel
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using Common;
using Business;
using System.Web.Mvc;
using System.Web.Security;
using System.Runtime.Remoting.Contexts;
namespace internetBankingApplication.ViewModel
{
public class NewFixedAccountViewModel
{
private account _Account { get; set; }
private fixedAccount _FixedAccount { get; set; }
public SelectList AccountTypes { get; set; }
public SelectList Durations { get; set; }
public SelectList AccountFromList { get; set; }
public SelectList Currencies { get; set; }
public int ID
{
get
{
return _Account.accountID;
}
}
[Required]
[Display(Name = "Account Name")]
public string Name
{
get
{
return _Account.name;
}
set
{
_Account.name = value;
}
}
[Required]
[Display(Name = "Account From")]
public int accountFrom { get;set;}
public string AccountFromName
{
get
{
string result = string.Empty;
try
{
result = ManageAccount.Instance.GetAccountBYID(accountFrom).name;
}
catch { }
return result;
}
}
[Required]
[Display(Name = "Duration")]
public int duration
{
get
{
return _FixedAccount.duration;
}
set
{
_FixedAccount.duration = value;
}
}
public string durationName
{
get
{
string result = string.Empty;
try
{
result = ManageDuration.Instance.GetDurationById(_FixedAccount.duration).duration1;
}
catch { }
return result;
}
}
[Required]
[Display(Name = "Available Balance")]
public decimal AvailableBalance
{
get
{
return _Account.availableBalance;
}
set
{
_Account.availableBalance = value;
}
}
[Required]
[Display(Name = "Currency")]
public int currency
{
get
{
return _Account.currency;
}
set
{
_Account.currency = value;
}
}
public string CurrencyName
{
get
{
string result = string.Empty;
try
{
result = ManageCurrency.Instance.getTypesByID(_Account.currency).name;
}
catch { }
return result;
}
}
[Required]
[Display(Name = "Account Description")]
public string Description
{
get
{
return _Account.description;
}
set
{
_Account.description = value;
}
}
[Required]
[Display(Name = "Account Renew")]
public bool renew
{
get
{
if (_FixedAccount.renew == 0)
{
return false;
}
return true;
}
set
{
if (value == false)
{
_FixedAccount.renew = 0;
}
else
{
_FixedAccount.renew = 1;
}
}
}
public NewFixedAccountViewModel()
{
// AccountTypes = new SelectList(
//ManageAccountType.Instance.getTypes(), "id", "type", _Account.typeID);
string username = HttpContext.Current.User.Identity.Name.ToString();
AccountFromList = new SelectList(
ManageAccount.Instance.GetUserAccounts(username), "accountID", "name", accountFrom);
**Currencies = new SelectList(
ManageCurrency.Instance.getCurrencies(), "id", "name",_Account.currency1.id);** //Giving the error
Durations = new SelectList(
ManageDuration.Instance.GetAllDurations(), "id", "duration", _FixedAccount.duration);
}
public NewFixedAccountViewModel(string username)
{
AccountTypes = new SelectList(
ManageAccountType.Instance.getTypes(), "id", "type", _Account.typeID);
AccountFromList = new SelectList(
ManageAccount.Instance.GetUserAccounts(username), "accountID", "name", accountFrom);
Currencies = new SelectList(
ManageCurrency.Instance.getCurrencies(), "id", "name", _Account.currency);
Durations = new SelectList(
ManageDuration.Instance.GetAllDurations(), "id", "duration", _FixedAccount.duration);
}
public NewFixedAccountViewModel(int accountID, string username)
{
_Account = ManageAccount.Instance.GetAccountBYID(accountID);
_FixedAccount = ManageFixedAccount.Instance.GetFixedAccountByID(accountID);
AccountFromList = new SelectList(
ManageAccount.Instance.GetUserAccounts(username), "accountID", "name", accountFrom);
AccountTypes = new SelectList(
ManageAccountType.Instance.getTypes(), "id", "type", _Account.accountType);
Currencies = new SelectList(
ManageCurrency.Instance.getCurrencies(), "id", "name", _Account.currency);
Durations = new SelectList(
ManageDuration.Instance.GetAllDurations(), "id", "duration", _FixedAccount.duration);
}
}
}
The error message you are getting means that you are trying to call a method or property on a null value - which you can't do.
From what I can see, either ManageCurrency is null or ManageCurrency.Instance is null.
If ManageCurrency is null the call to the Property Instance fails, as null objects have no methods or properties. Similarly, if ManageCurrency.Instance is null, the call to the Method getCurrencies fails for the same reason.
In any case - this is not too hard to debug. As skumar suggests, set a breakpoint on that line, run in debug mode, and see where the null value is, and then work backwards to discover why the value is null.
The username you are passing in the following code could be Empty or Invalid. That is why it returns NULL and above exception occurs.
AccountFromList = new SelectList(
ManageAccount.Instance.GetUserAccounts(username), "accountID", "name", accountFrom);
I have code-first based context with following entities:
public class City : IEquatable<City>
{
public City()
{
Posts = new List<Post>();
}
public City(string cityName) : this()
{
Name = cityName;
}
public virtual ICollection<Post> Posts { get; private set; }
public int Id { get; set; }
public string Name { get; private set; }
protected string LoweredName
{
get { return Name.ToLower(CultureInfo.CurrentCulture); }
}
public override bool Equals(object obj)
{
bool equals = false;
var city = obj as City;
if (city != null)
equals = Equals(city);
return equals;
}
public override int GetHashCode()
{
int idHash = Id.GetHashCode();
int nameHash = LoweredName.GetHashCode();
var hashCode = idHash ^ nameHash;
return hashCode;
}
public bool Equals(City other)
{
return Id == other.Id && LoweredName == other.Name.ToLower(CultureInfo.CurrentCulture);
}
}
public class Post : IEquatable<Post>
{
public Post()
{
Addresses = new List<PostalAddress>();
}
public virtual ICollection<PostalAddress> Addresses { get; private set; }
public virtual City City { get; set; }
public int Id { get; set; }
public string ZipCode { get; set; }
protected string LoweredZipCode { get { return ZipCode.ToLower(CultureInfo.CurrentCulture); } }
public bool Equals(Post other)
{
return Id == other.Id && City.Equals(other.City) && LoweredZipCode == other.ZipCode.ToLower(CultureInfo.CurrentCulture);
}
}
DbContext has defined those entities in method OnModelCreating:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Configurations.Add(new CityMap());
modelBuilder.Configurations.Add(new PostMap());
}
public class CityMap : EntityTypeConfiguration<City>
{
public CityMap()
{
// Primary Key
HasKey(t => t.Id);
// Properties
// Table & Column Mappings
ToTable("City");
Property(t => t.Id).HasColumnName("Id");
Property(t => t.Name)
.HasColumnName("Name")
.HasMaxLength(450);
}
}
public class PostMap : EntityTypeConfiguration<Post>
{
public PostMap()
{
// Primary Key
HasKey(t => t.Id);
// Properties
// Table & Column Mappings
ToTable("Post");
Property(t => t.Id)
.HasColumnName("Id");
Property(t => t.ZipCode)
.HasColumnName("ZipCode")
.HasMaxLength(450);
// Relationships
HasRequired(t => t.City)
.WithMany(t => t.Posts)
.Map(map => map.MapKey("CityId"));
}
}
I've readed some data as POCO object and inserted them into List collection
public class PostImportObject : IEquatable<PostImportObject>
{
private string _city;
private string _loweredCity;
public string City
{
get { return _city; }
set
{
_city = value.CapitalizeFirstLetter();
_loweredCity = value.ToLower(CultureInfo.CurrentCulture);
}
}
public string ZipCode
{
get { return _zipValue; }
set { _zipValue = value.ToLower(CultureInfo.CurrentCulture); }
}
protected string LoweredCity
{
get { return _loweredCity; }
}
public override bool Equals(object obj)
{
bool equals = false;
var postImport = obj as PostImportObject;
if (postImport != null)
{
equals = Equals(postImport);
}
return equals;
}
public override int GetHashCode()
{
int ziphash = ZipCode.GetHashCode();
int cityHash = LoweredCity.GetHashCode();
var hashCode = ziphash ^ cityHash;
return hashCode;
}
public bool Equals(PostImportObject other)
{
bool equals = _loweredCity == other.City.ToLower(CultureInfo.CurrentCulture) && ZipCode == other.ZipCode;
return equals;
}
}
If I query data in import list and in database too, my following queries return the same Exception:
using(var db = new DbContext())
{
var query1 = from post2 in db.Posts.Include("City")
join mergedPost in mergedPosts on new PostImportObject() {City = post2.City.Name, ZipCode = post2.ZipCode} equals new PostImportObject() {City = mergedPost.City, ZipCode = mergedPost.ZipCode} into joinedPosts
from joinedPost in joinedPosts.DefaultIfEmpty()
where joinedPosts==null
select post2;
var query2= from city1 in db.Cities
join postImportObject in mergedPosts on city1.Name equals postImportObject.City
join post1 in db.Posts on city1 equals post1.City
select post1;
}
I'll get following exception when querying Any() method of query1 or query2:
Index (zero based) must be greater than or equal to zero and less than the size of the argument list
I'm sorry that I created another topic with same subject, but I didn't find solution for my problem in other topics.
Looking at the stack trace, I'm guessing there's a problem with the translated version of the ELinq_UnsupportedConstant resource. The English version of this error message is: Unable to create a constant value of type '{0}'. Only primitive types ('{1}') are supported in this context.
I think you have two problems:
For a join, the composite key needs to be an anonymous type; you can't use your PostImportObject as the join key in query1;
You can't join a database table to a local list;
I think you'll need to use .AsEnumerable() to pull the entire list into memory before you can join to the local list:
var query = from post in context.Posts.Include(p => p.City).AsEnumerable()
join mergedPost in mergedPosts
on new { City = post.City.Name, post.ZipCode }
equals new { mergedPost.City, mergedPost.ZipCode }
into joinedPosts
from joinedPost in joinedPosts.DefaultIfEmpty()
where joinedPost == null
select post;
Does anyone know why the following c# mvc.net code gives a null ref exception when databainding the list to the jqgrid?
This is a cutdown example to illustrate the problem.
If I change
DataField = "MyClass.Id"
to
DataField = "Id"
It binds just fine, but in my real code I am trying to bind to an object with 2 subobjects and am trying to display data from both on the same grid.
Any suggestions much appreciated.
Thanks
(I saw this post but it didn't get answered: jqgrid List of objects (with sub objects) as datasource)
internal class MyWrapper
{
public MyClass MyClass { get; set; }
public int Id { get; set; }
}
internal class MyClass
{
public int Id { get; set; }
}
public class TestController : Controller
{
public ActionResult Index()
{
return View(GetGrid());
}
public JsonResult SearchGridDataRequested()
{
return GetGrid().DataBind(GetModel().AsQueryable());
}
private JQGrid GetGrid()
{
return new JQGrid
{
ID = "MyGrid",
DataUrl = Url.Action("SearchGridDataRequested"),
Width = Unit.Pixel(700),
Columns = new List<JQGridColumn>
{
new JQGridColumn
{
DataField = "MyClass.Id",
PrimaryKey = true,
DataType = typeof (int)
}
}
};
}
private static IEnumerable<MyWrapper> GetModel()
{
return new List<MyWrapper>
{
new MyWrapper {Id = 1, MyClass = new MyClass {Id = 11}},
new MyWrapper {Id = 2, MyClass = new MyClass {Id = 12}},
new MyWrapper {Id = 3, MyClass = new MyClass {Id = 13}}
};
}
}
I created a local db with helper app project. and deployed it from isolate storage to installation folder,i added to project directory with content build action by add existing item. my problem is that i want to insert data, but i don't know how to move the db file to isolate storage to insert and data must add to my .sdf file that is locate in my project directory also.
Souphia,
While learning to use WP, I wrote a simple application that tracked tasks.
One version of that app stored all task data in Sql on the phone.
You can read the post and download all the code for the app here:
http://www.ritzcovan.com/2012/02/building-a-simple-windows-phone-app-part-3/
But, here is some of the code from that project:
First we have the model class decorated with the appropriate attributes:
[Table]
public class Task : INotifyPropertyChanged, INotifyPropertyChanging
{
[Column(IsDbGenerated = false, IsPrimaryKey = true, CanBeNull = false)]
public string Id
{
get { return _id; }
set
{
NotifyPropertyChanging("Id");
_id = value;
NotifyPropertyChanging("Id");
}
}
[Column]
public string Name
{
get { return _name; }
set
{
NotifyPropertyChanging("Name");
_name = value;
NotifyPropertyChanged("Name");
}
}
[Column]
public string Category
{
get { return _category; }
set
{
NotifyPropertyChanging("Category");
_category = value;
NotifyPropertyChanged("Category");
}
}
[Column]
public DateTime? DueDate
{
get { return _dueDate; }
set
{
NotifyPropertyChanging("DueDate");
_dueDate = value;
NotifyPropertyChanged("DueDate");
}
}
[Column]
public DateTime? CreateDate
{
get { return _createDate; }
set
{
NotifyPropertyChanging("CreateDate");
_createDate = value;
NotifyPropertyChanged("CreateDate");
}
}
[Column]
public bool IsComplete
{
get { return _isComplete; }
set
{
NotifyPropertyChanging("IsComplete");
_isComplete = value;
NotifyPropertyChanged("IsComplete");
}
}
[Column(IsVersion = true)] private Binary _version;
private string _id;
private bool _isComplete;
private DateTime? _createDate;
private DateTime? _dueDate;
private string _name;
private string _category;
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangingEventHandler PropertyChanging;
public void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
public void NotifyPropertyChanging(string property)
{
if (PropertyChanging != null)
PropertyChanging(this, new PropertyChangingEventArgs(property));
}
}
In the constructor in app.xaml.cs, I have the following:
TaskMasterDataContext = new TaskMasterDataContext();
if (!TaskMasterDataContext.DatabaseExists())
{
TaskMasterDataContext.CreateDatabase();
DatabaseHelper.SetupDatabase(TaskMasterDataContext);
}
and here is the TaskMasterDataContext.cs code
public class TaskMasterDataContext : DataContext
{
public TaskMasterDataContext() : base("Data Source=isostore:/TaskMasterData.sdf")
{
}
public Table<Task> Tasks;
}
public static class DatabaseHelper
{
public static void SetupDatabase(TaskMasterDataContext dataContext)
{
string category = string.Empty;
var tasks = new List<Task>();
for (int i = 0; i < 20; i++)
{
tasks.Add(new Task()
{
Id = System.Guid.NewGuid().ToString(),
Category = GetCategoryString(i),
CreateDate = DateTime.Now,
DueDate = DateTime.Now.AddDays(new Random().Next(1, 30)),
IsComplete = false,
Name = String.Format("{0} Task # {1}", GetCategoryString(i), i)
});
}
dataContext.Tasks.InsertAllOnSubmit(tasks);
dataContext.SubmitChanges();
}
private static string GetCategoryString(int i)
{
if (i%2 == 0)
return "home";
if (i%3 == 0)
return "personal";
return "work";
}
}
The DatabaseHelper class is just there to populate the DB with some test data after its created.
I hope this helps.