c# List adding items using For loop - c#

I have a problem with c# List, not sure where I'm missing the point while adding a new object to the Managepagesid List!
public class Clients
{
[BsonId]
public string Id { get; set; } //Object ID managed by MongoDb
public string Name { get; set; } //Client Name
public string Phone { get; set; } //Client Phone
public string Email { get; set; } //Client E-mail
public string Username { get; set; } //Client Username
public DateTime LastModified { get; set; } //Client Last Login
public string FB_User_Id { get; set; } //Client FB User ID
public AccessToken UserAccessToken { get; set; } //AccessToken which is stored while user is logged in.
public List<ManagePages> Manage_Pages_id { get; set; } //The pages maintained by the specific client
}
I'm trying to access add a new item into ManagePage_id list but its thrwing some null exception.. Help!
Clients client = new Clients();
client.FB_User_Id = FBData.id;
client.Name = FBData.name;
client.Email = FBData.email;
client.Username = FBData.username;
for (int index = 0; index < FBData.accounts["data"].Count; index++)
{
ManagePages pagedetails = new ManagePages()
{
page_id = FBData.accounts["data"][index].id,
page_name = FBData.accounts["data"][index].name,
ManagePages_AccessTokens = new AccessToken()
{
AccessToken_accessToken = FBData.accounts["data"][index].access_token,
AccessToken_expiryDate = DateTime.Now
},
ManagePages_category = FBData.accounts["data"][index].category
};
var category = pagedetails.ManagePages_category;
client.Manage_Pages_id.Add(pagedetails);
}
Stack Trace added!
Exception>System.NullReferenceExceptionObject reference not set to an instance of an object. at Vega_MongoDB.FBDataAccess.ClientFBRepository.ClientsData(String accessToken) in g:\Development\Vega_MongoDB\Vega_MongoDB\FBDataAccess\ClientFBRepository.cs:line 48
at Vega_MongoDB.Models.ClientRepository..ctor(String connection) in g:\Development\Vega_MongoDB\Vega_MongoDB\Models\Clients\ClientRepository.cs:line 47
at Vega_MongoDB.Models.ClientRepository..ctor() in g:\Development\Vega_MongoDB\Vega_MongoDB\Models\Clients\ClientRepository.cs:line 23
at Vega_MongoDB.Controllers.ClientsController..cctor() in g:\Development\Vega_MongoDB\Vega_MongoDB\Controllers\ClientsController.cs:line 18
And I have checked the pagedetails object, it contains all the data..
Thanks
Vishnu

You should create an instance of the list before adding item:
client.Manage_Pages_id = new List<ManagePages>();
for (int index = 0; index < FBData.accounts["data"].Count; index++)
{
ManagePages pagedetails = new ManagePages()
{
page_id = FBData.accounts["data"][index].id,
page_name = FBData.accounts["data"][index].name,
ManagePages_AccessTokens = new AccessToken()
{
AccessToken_accessToken = FBData.accounts["data"][index].access_token,
AccessToken_expiryDate = DateTime.Now
},
ManagePages_category = FBData.accounts["data"][index].category
};
var category = pagedetails.ManagePages_category;
client.Manage_Pages_id.Add(pagedetails);
}

Try adding this to your class:
public Clients()
{
this.Manage_Pages_id = new List<ManagePages>();
}

You need to initialize your list before adding anything to it. You can do this in the constructor for the Clients class or in your calling code (as Artem suggested).
public class Clients
{
//properties
public Clients()
{
Manage_Pages_id = new List<ManagePages>();
}
}

Related

Initialize object array inside another array c#

I have the following class
public class ResProductSetupData
{
public List<ProductSetup> data { get; set; }
}
public class ProductSetup
{
public List<Fundtype> FundType { get; set; }
}
public class Fundtype
{
public string FundType { get; set; }
public bool IsGIO { get; set; }
public string ReportCode { get; set; }
public List<Fundlist> FundList { get; set; }
}
public class Fundlist
{
public string FundCode { get; set; }
public string FundDesc { get; set; }
public decimal MinAllocation { get; set; }
public string VPMSField { get; set; }
public string FundSpec { get; set; }
}
Now I want to initialize this object inside another file so that I can fill its values. Fundtype is a list and FundList is another list inside FundType.
ProductSetup prodSetup = new ProductSetup();
Fundtype fundType = new Fundtype();
Fundlist fundlist = new Fundlist();
So Inside a foreach loop I instantiated these objects
prodSetup.FundType = new List<Fundtype>();
foreach (var fund in fundTypeData)
{
fundType.FundType = fund.FundType;
fundType.IsGIO = fund.IsGIO;
fundType.ReportCode = "";
prodSetup.FundType.Add(fundType);
var listOfFund = GetProductFund(prodSetup.ProdCode, fund.FundType);
int i = 0;
foreach (var listFundData in listOfFund)
{
var fundDetails = GetFundDetails(listFundData.FundCode);
fundlist.FundCode = listFundData.FundCode;
fundlist.VPMSField = listFundData.VPMSField;
fundlist.FundDesc = fundDetails[0].FundDesc;
fundlist.MinAllocation = fundDetails[0].MinAllocation;
fundlist.FundSpec = fundDetails[0].FundSpec;
prodSetup.FundType[i].FundList.Add(fundlist);
i++;
}
}
When I add data into the Fundlist list, an error will show System.NullReferenceException: 'Object reference not set to an instance of an object.'. I know I have to instantiate first, but I dont know how. Any help would be appreciated.
Update, I have instantiated the FundList array as below
int i = 0;
foreach (var listFundData in listOfFund)
{
prodSetup.FundType[i].FundList = new List<Fundlist>();
var fundDetails = GetFundDetails(listFundData.FundCode);
fundlist.FundCode = listFundData.FundCode;
fundlist.VPMSField = listFundData.VPMSField;
fundlist.FundDesc = fundDetails[0].FundDesc;
fundlist.MinAllocation = fundDetails[0].MinAllocation;
fundlist.FundSpec = fundDetails[0].FundSpec;
prodSetup.FundType[i].FundList.Add(fundlist);
i++;
}
The first index [0] is fine. But when it loops to the second index to instantiate the second index [1], it throws another error Index was out of range. Must be non-negative and less than the size of the collection.\r\nParameter name: index

Something is getting wrong with adding a list to existing List

I'm trying to realize the listBox with List where i getting some variable.
And when i wonna to add a new "Object" to static List i getting a NullReferenceException
This is my code where i adding a new List
if (EventArgsIn.Message.Chat.Id == MainChatId)
{
if (EventArgsIn.Message.ReplyToMessage != null)
{
var _tempMessage = new listBoxMessage()
{
From = EventArgsIn.Message.From.Username,
FromId = EventArgsIn.Message.From.Id,
MessageId = EventArgsIn.Message.MessageId,
MessageText = EventArgsIn.Message.Text,
MessageIdReply = 0
};
tempMessageMain.Add(_tempMessage);
} else
{
var _tempMessage = new listBoxMessage() {
From = EventArgsIn.Message.From.Username,
FromId = EventArgsIn.Message.From.Id,
MessageId = EventArgsIn.Message.MessageId,
MessageText = EventArgsIn.Message.Text,
MessageIdReply = 0
};
tempMessageMain.Add(_tempMessage);
}
}
And here is my static List
public static List<listBoxMessage> tempMessageMain;
A-a-and my class where i doing Template
public class listBoxMessage
{
public listBoxMessage()
{
}
public string From { get; set; }
public int FromId { get; set; }
public int MessageId { get; set; }
public string MessageText { get; set; }
public int MessageIdReply { get; set; }
}
}
This is test code*
You declared a listbox with next line:
public static List<listBoxMessage> tempMessageMain;
The value of tempMessageMain is still null.
Now you have to create a new instance of tempMessageMain:
public static List<listBoxMessage> tempMessageMain = new List<listBoxMessage>();

How to add to a RavenDB List<type> in .net

Update: I fixed it by copy pasting the working code into a new clean project. I have no idea why I was getting that bug, but as long as it's gone
I'm having problems figuring exactly how to do what I want.
In this instance, what I have is a db of merchants, and I want to be able to add venues as a list to the merchant entry in the database. For some reason I cannot figure out why, I can fetch the merchant, but cannot seem to get a hold of the id of the entry that I have fetched and then update it. (I'm having some problems with updating as well, From what I've seen I need the Id of the entry I want, and then I can update with a patch... right?)
Here is my Json class:
public class Merchant
{
[JsonProperty(PropertyName = "name")]
public string name { get; set; }
[JsonProperty(PropertyName = "venues")]
public List<Venue> venues { get; set; }
}
public class Venue
{
[JsonProperty(PropertyName = "name")]
public string name { get; set; }
[JsonProperty(PropertyName = "tills")]
public List<Till> tills { get; set; }
}
public class Till
{
[JsonProperty(PropertyName = "name")]
public string name { get; set; }
}
Here's my RavenDB Handler class's functions that are relevent:
public List<JObject> QueryFromDb(string query)
{
List<Object> objReturned;
List<JObject> jObjects = new List<JObject>();
using (IDocumentSession session = store.OpenSession())
{
objReturned = session
.Advanced.RawQuery<Object>(query)
.ToList();
}
for (var i = 0; i < objReturned.Count; i++)
{
var json = JsonConvert.SerializeObject(objReturned[i], Formatting.Indented);
jObjects.Add(JObject.Parse( json.ToString()));
}
return jObjects;
}
public String GetJsonFromDB(string query)
{
string returnStr = "";
List<JObject> myResponse = QueryFromDb(query);
for (var i = 0; i < myResponse.Count; i++)
{
var json = JsonConvert.SerializeObject(myResponse[i], Formatting.Indented);
returnStr += json.ToString();
}
return returnStr;
}
And here is me trying to get ahold of the Id of the ravendb entry:
public void UpdateMerchantList()
{
merchantGrid.Rows.Clear();
List<JObject> myResponse = ravenDB.QueryFromDb("from Merchants");
for (var i = 0; i < myResponse.Count; i++)
{
var json = JsonConvert.SerializeObject(myResponse[i], Formatting.Indented);
Merchant merchant = new Merchant(json.ToString());
if (myResponse[i].Property("Id") != null) { merchant.MyID = myResponse[i].Property("Id").ToString(); }
merchantGrid.Rows.Add(merchant.MyID, merchant.name);
}
}
For some reason, I took this code and transplanted it into a console app, and got it to work with this code:
List<JObject> result = ravenDb.QueryFromDb("from Merchants");
for(var i = 0; i < result.Count; i++)
{
Console.WriteLine(result[i].Property("Id").ToString());
}
Which does give me the exact stuff I want:
"Id": "merchants/97-A"
"Id": "merchants/98-A"
"Id": "merchants/129-A"
"Id": "merchants/130-A"
But when I transplant it backinto my form and try to add this to the datagridview I cannot see it anymore.
update: have been able to add to the list into the merchant class in the console app. Here is the code.
public void AddVenue(string idArg,Venue venue)
{
using (IDocumentSession session = store.OpenSession())
{
var merchant = session.Load<Merchant>(idArg);
List<Venue> venuesList = new List<Venue>();
if (merchant.venues == null) { session.Advanced.Patch(merchant, m => m.venues, venuesList); }
else
{
session.Advanced.Patch(merchant,
x => x.venues,
venues => venues.Add(venue));
}
session.SaveChanges();
}
}
Just so people understand what I'm talking about: here is the json that outputs from the form application:
Why?
when in console with pretty much identical code (copy pasted) I get this:
I'm getting more data from one application than the other, and I really really want the id.
I'm going to refactor the code into a wcf application I guess. Just because. Maybe I'll accidentally fix it doing that.
You can load directly the object of given class, no need to handle JSON (de)serialization yourself, unless there is a specific reason to do so.
Also, using patching is more useful when you don't want to load the document (to save bandwidth). When you already have the document loaded, you can simply change it and save the changes.
See the following code for reference:
public class Merchant
{
// note added Id property
public string Id { get; set; }
[JsonProperty(PropertyName = "name")]
public string name { get; set; }
[JsonProperty(PropertyName = "venues")]
public List<Venue> venues { get; set; }
}
public class Venue
{
[JsonProperty(PropertyName = "name")]
public string name { get; set; }
[JsonProperty(PropertyName = "tills")]
public List<Till> tills { get; set; }
}
public class Till
{
[JsonProperty(PropertyName = "name")]
public string name { get; set; }
}
public void MerchantsTest()
{
using (var store = GetDocumentStore())
{
using (var session = store.OpenSession())
{
session.Store(new Merchant { Id = "merchant-1", name = "merchant1", venues = new List<Venue> { new Venue { name = "venue-1A", tills = new List<Till> { new Till { name = "till-1A-first" } } } } });
session.Store(new Merchant { Id = "merchant-2", name = "merchant2", venues = new List<Venue> { new Venue { name = "venue-2A", tills = new List<Till> { new Till { name = "till-2A-first" } } } } });
session.SaveChanges();
}
using (var session = store.OpenSession())
{
// you can load all merchants
var merchants = session.Query<Merchant>(null, "Merchants").ToList();
// or load specific merchant by ID
var merchant2 = session.Load<Merchant>("merchant-1");
// add a venue to a loaded merchant (not using patch but simply adding the object)
merchant2.venues.Add(new Venue { name = "venue-2B", tills = new List<Till> { new Till { name = "till-2B-first" } } });
session.SaveChanges();
}
}
}

How do I create and insert one-to-many object with entity framework c#

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>();
}

Entity Framework - Conditionally include related entities

I maintain an API that, based on a request for a list of people, returns a different result set based on the request. For example, some API clients want to get a list of people and a list of their interactions, others want people and a list of their metadata. All this can be specified int he request to the API method that returns people.
This does not appear to work:
using (var dbcontext = new ExampleEntities())
{
var query = dbcontext.People.AsQueryable();
//determined in earlier application logic based on request
if(includeMetadata)
{
query = query.Include("metadata");
}
//determined in earlier application logic based on request
if(includeInteractions)
{
query = query.Include("interactions");
}
/* ...SNIP... */
}
What I don't want to do is this:
var query = dbcontext.People.Include("Metadata").Include("interactions");
which will mean every request to get a person will include ALL their related entities, even if the requesting API client does not need them.
I also don't want to code every possible combination of logic:
if(includeMetadata && includeInteractions)
{
var query = dbcontext.People.Include("Metadata").Include("interactions");
}
else if(includeMetadata)
{
var query = dbcontext.People.Include("Metadata");
}
else if(includeInteractions)
{
var query = dbcontext.People.Include("Interactions");
}
else
{
var query = dbcontext.People;
}
This will result in hard-to-maintain code, however, I realize I could code generate this if needed.
You can chain the IQueryable's
using (var dbcontext = new ExampleEntities())
{
var query = dbcontext.People.AsQueryable();
if(includeMetadata)
{
query = query.Include("metadata");
}
if(includeInteractions)
{
query = query.Include("interactions");
}
}
Your first example should work if you replace u with query
u = u.Include("metadata");
with
query = query.Include("metadata");
Works fine here... checking the sql statements with the EF 6 Log handler
[TestClass]
public void SomeTestClass
{
[TestMethod]
public void ShouldLoadOnlyRequiredCollections()
{
Database.SetInitializer(new DropCreateDatabaseAlways<HomesContext>());
var db = new HomesContext();
Assert.IsFalse(db.Homes.Any());
var home = db.Homes.Create();
db.Homes.Add(home);
home.Staff.Add(new Staff { Name = "wilma" });
home.Staff.Add(new Staff { Name = "betty" });
home.Residents.Add(new Resident { Name = "fred" });
home.Residents.Add(new Resident { Name = "barney" });
db.SaveChanges();
db = null;
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<HomesContext>());
var sb = new StringBuilder();
db = new HomesContext();
db.Database.Log = ((s) => { sb.Append(s + "\r"); });
Assert.IsTrue(db.Homes.Any());
string log;
log = sb.ToString();
Assert.IsTrue(sb.ToString().Contains("FROM [dbo].[Homes]"));
sb = new StringBuilder(); //ok get residents
var q = db.Homes.Include("Residents");
Assert.IsTrue(string.IsNullOrEmpty(sb.ToString()));
var lst = q.ToList();
log = sb.ToString();
Assert.IsTrue(sb.ToString().Contains("[dbo].[Homes]"));
Assert.IsTrue(sb.ToString().Contains("[dbo].[Residents]"));
Assert.IsTrue(!sb.ToString().Contains("[dbo].[Staff]"));
sb = new StringBuilder(); //get staff
q = db.Homes.Include("Staff");
Assert.IsTrue(string.IsNullOrEmpty(sb.ToString()));
lst = q.ToList();
log = sb.ToString();
Assert.IsTrue(log.Contains("[dbo].[Homes]"));
Assert.IsTrue(!log.Contains("[dbo].[Residents]"));
Assert.IsTrue(log.Contains("[dbo].[Staffs"));
sb = new StringBuilder(); //get residents and staff
q = db.Homes.Include("Staff");
q = q.Include("Residents");
lst = q.ToList();
log = sb.ToString();
Assert.IsTrue(log.Contains("[dbo].[Homes]"));
Assert.IsTrue(log.Contains("[dbo].[Residents]"));
Assert.IsTrue(log.Contains("[dbo].[Staffs]"));
}
}
public class HomesContext:DbContext
{
public DbSet<Home> Homes { get; set; }
}
public class Home
{
public Home()
{
Staff = new List<Staff>();
Residents = new List<Resident>();
}
public int HomeId { get; set; }
public string HomeName { get; set; }
public int MaxResidents { get; set; }
public int MaxStaff { get; set; }
public int CurrentResidents { get; set; }
[NotMapped]
public int CurrentStaff { get; set; }
public IList<Staff> Staff { get; set; }
public IList<Resident> Residents { get; set; }
}
public class Staff
{
public int StaffId { get; set; }
public string Name { get; set; }
public int HomeId { get; set; }
public Home Home { get; set; }
}
public class Resident
{
public int ResidentId { get; set; }
public string Name { get; set; }
public int HomeId { get; set; }
public Home Home { get; set; }
}

Categories