I have class SellStatement
public class SellStatement
{
public long billNo
public DateTime paymentDate;
public List<string> ProductName;
public List<double> quantity;
public List<double> ratePerQuantity;
}
When i am trying to access function GetSaleDetails
public Exception GetSaleDetails(List<SellStatement> lss1,string query)
{
try
{
for (int i = 0; i < lss1.ToArray().Length; i++)
{
query = "select * from [product details] where [bill no]=#billno";
com = new SqlCeCommand(query, con);
con.Open();
com.Parameters.AddWithValue("#billno",lss1[i].billNo);
sdr = com.ExecuteReader();
while (sdr.Read())
{
lss1[i].ProductName.Add(sdr.GetString(1));//Exception line
lss1[i].quantity.Add(sdr.GetDouble(2));
lss1[i].ratePerQuantity.Add(sdr.GetDouble(3));
}
}
con.Close();
return null;
}
catch (Exception e)
{
con.Close();
return e;
}
}
Null Reference Exception comes up atlss1[i].ProductName.Add(sdr.GetString(1));.I think error might be because of null value in at sdr.GetString(1) but i checked it has some value .My friend told me that you can't change Function argument value like this so i try to copy one list to other like this .
List<SellStatement> lss1 = new List<SellStatement>() ;
lss1.AddRange(lss);
But it doesn't help me out. I am not able to figure out what's wrong while adding element.
If you showed us your complete SellStatement class in the question, then the reason is clear:
You never initialized ProductName, quantity and ratePerQuantity. They are null and that's exactly what the exception is telling you.
To fix it, change your class to this:
public class SellStatement
{
public long billNo
public DateTime paymentDate;
public List<string> ProductName = new List<string>();
public List<double> quantity = new List<double>();
public List<double> ratePerQuantity = new List<double>();
}
Please note that this goes against the normal C# design guidelines that say you shouldn't have public fields. Consider redesigning your class like so:
public class SellStatement
{
List<string> _productName = new List<string>();
List<double> _quantity = new List<double>();
List<double> _ratePerQuantity = new List<double>();
public long billNo {get; set;}
public DateTime paymentDate {get; set;}
public List<string> ProductName { get { return _productName; } }
public List<double> quantity { get { return _quantity; } }
public List<double> ratePerQuantity { get { return _ratePerQuantity; } }
}
Related
public static List<StudentModel> LoadPointCounts()
{
using (IDbConnection cnn = new SQLiteConnection(LoadConnectionString()))
{
var output = cnn.Query<StudentModel>("SELECT PointCount FROM Student");
return output.ToList();
}
}
My values for each index in the list are just "ClassroomRaffle.StudentModel" when it should be a numeric value. Anything that jumps out to you guys here?
EDIT: Those who asked, here is the StudentModel
public class StudentModel
{
public int Id { get; set; }
public string Name { get; set; }
public int PointCount { get; set; }
}
And here is how I am displaying the data from the list. (not completed yet, I plan on adding a loop to go through each value)
pointcounts = LoadPointCounts();
label.Text = pointcounts[0].ToString();
You are asking for and getting back a List of StudentModel, not a list of integers.
If you just want the ints, something like:
public static List<int> LoadPointCounts()
{
using (IDbConnection cnn = new SQLiteConnection(LoadConnectionString()))
{
var output = cnn.Query<int>("SELECT PointCount FROM Student");
return output.Select(i => i).ToList();
}
}
public class PriceDetail
{
public int ID{ get; set; }
public string Package { get; set; }
public string Currency { get; set; }
public int Price { get; set; }
public string PackageType { get; set; }
public List<string> Items { get; set; }
}
[WebMethod]
public static string GetCardDetail(string category)
{
string cs = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
List<PriceDetail> pricingCard = new List<PriceDetail>();
string query = "select [PricingID],[Package],[Currency],[Price],[PackageType] from [SeoDatabase].[dbo].[tbl_Pricing] where Category = #Category";
SqlConnection con = new SqlConnection(cs);
SqlCommand cmd = new SqlCommand(query, con);
cmd.Parameters.AddWithValue("#Category", category);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
PriceDetail priceDetail = new PriceDetail();
priceDetail.ID = Convert.ToInt16(rdr["PricingID"]);
priceDetail.Package = rdr["Package"].ToString();
priceDetail.Currency = rdr["Currency"].ToString();
priceDetail.Price = Convert.ToInt16(rdr["Price"]);
priceDetail.PackageType = rdr["PackageType"].ToString();
pricingCard.Add(priceDetail);
}
con.Close();
List<string> items = new List<string>();
string queryList = "select [Item] from [SeoDatabase].[dbo].[tbl_PricingItem] where PricingID = #pricingID";
int i = 0;
while(i < pricingCard.Count)
{
SqlCommand listCmd = new SqlCommand(queryList, con);
con.Open();
listCmd.Parameters.AddWithValue("#pricingID", pricingCard[i].ID);
SqlDataReader listReader = listCmd.ExecuteReader();
while (listReader.Read())
{
items.Add(listReader["Item"].ToString());
}
pricingCard[i].Items = items;
items.Clear();
con.Close();
i++;
}
string obj = JsonConvert.SerializeObject(pricingCard);
return obj;
}
Every thing is going good when i reached on second loop while(i < pricingCard.Count) in this loop on 0 index its working properly and assigning right value to pricingCard[i].Items = items; problem is that when it goes for second index(1) it assigns the value correctly but also change the value of first index(0) and when loop moves for third time it changes the value of index(0).Items and index(1).Items with index(2).Items values
Please help me to solve
The reason this is not behaving as you might expect is that items, being of type List<string>, is a reference type, not a value type. This a concept that you will need to understand well whilst developing with managed languages such as C#. MSDN - Reference and Value
Simplistically , what you are saying by pricingCard[i].Items = items; is that pricingCard[i].Items is now a reference to items. That means, at any given point after, an evaluation of pricingCard[i].Items will just "refer" you to items, therefore any changes to items will reflect on all reference you have made to it.
What you need to do, at the being of each loop, is to "re-instantiating" items with items = new List<string>(). This is to say: create a new instance of the list, and new instance to with the next iteration of pricingCard[i].Items will refer.
while(i < pricingCard.Count)
{
items = new List<string>();
// Do the rest of your process
}
Alternatively, add the items directly:
while (listReader.Read())
{
pricingCard[i].Items.Add(listReader["Item"].ToString());
}
P.S.
Rather than using:
int i = 0;
while(i < pricingCard.Count)
{
i++;
}
Try:
for (int i = 0; i < pricingCard.Count; i++)
{}
I have a csv file that looks like this:
M;2017.12.01 17:04;1;example#example.com
T;1;K001;2
T;1;N001;1
M;2017.11.01 15:56;2;example#example.com
T;2;P001;2
T;2;P001;1
My problem is that I have to read this file into a List<> and be able to navigate in it with indexes but the different types of rows after the long ones are confusing me.
class Order
{
public string Type { get; set; }
public DateTime Date { get; set; }
public string OrderID { get; set; }
public string Email { get; set; }
public string ItemNumber { get; set; }
public int Quantity { get; set; }
public Order(string[] ordered , string[] items)
{
Type = ordered[0];
Date = DateTime.Parse(ordered[1]);
OrderID = ordered[2];
Email = ordered[3];
Type = items[0];
OrderID = items[1];
ItemNumber = items[2];
Quantity = int.Parse(items[3]);
}
}
class Program
{
static List<Order> orders = new List<Order>();
static void Main(string[] args)
{
Reading();
}
private static void Reading()
{
using (System.IO.StreamReader reader = new System.IO.StreamReader("orders.csv"))
{
while (!reader.EndOfStream)
{
orders.Add(new Order(reader.ReadLine().Split(';') , reader.ReadLine().Split(';')));
}
}
}
}
You can try to identify the line before creating it.
Than you can create two different methods to initialize your order.
while (!reader.EndOfStream)
{
var values = reader.ReadLine().Split(';');
if(DateTime.TryParse(values.Skip(1).First(), out var date)) {
orders.Add(Order.FromOrderWithDate(values));
}
else
orders.Last().Items.Add(Item.FromOrderWithEmail(values));
}
The two methods will be something like
public static Order FromRow(string[] ordered) =>
new Order {
Type = ordered[0],
Date = DateTime.Parse(ordered[1]),
OrderID = ordered[2],
Email = ordered[3],
Items = new List<Item>();
};
public static Item FromRow(string[] items) =>
new Item {
Type = items[0],
OrderID = items[1],
ItemNumber = items[2],
Quantity = int.Parse(items[3])
};
And finally two different class, one for order and one for item, the Order should contain a list for the items.
Try something like:
List<Customer> customers = new List<Customer>();
Customer lastCustomer = null;
foreach(var line in File.ReadLines("orders.csv"))
{
var values = line.Split(';');
if (values[0]=="M")
{
lastCustomer = new Customer(values);
customes.Add(lastCustomer);
}
else if (values[0]=="T" && lastCustomer != null)
{
lastCustomer.AddOrder(values);
}
}
(you'll need to write a Customer class that can construct its self from an array of strings, plus has a method for adding new Order objects to its own list of orders, again constructing them from an array)
I have the following method in DAL which accepts the model OrderList and returns a List<OrderList>
public List<OrderList> GetOrderList(OrderList orderList)
{
...
return new List<OrderList>();
}
When I analyze using FXCop, it's saying DoNotExposeGenericLists Error
FXCop is saying this as resolution
"Change 'List<OrderList>' in 'OrderRelatedDataAccess.GetOrderList(OrderList)' to use
Collection<T>, ReadOnlyCollection<T> or KeyedCollection<K,V>"
How can I correct this?
My OrderList model is shown below
public int serialNumber { get; set; }
public int orderID { get; set; }
public int orderListID { get; set; }
public int productID { get; set; }
public int quantity { get; set; }
public long price { get; set; }
public string productName { get; set; }
Thanks.
Edit:
Code inside the method
List<OrderList> listOfOrderList = new List<OrderList>();
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand("sGetOrderListByOrderID", connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#orderID", orderList.orderID);
connection.Open();
reader = command.ExecuteReader();
int sno = 0;
while (reader.Read())
{
long price = long.Parse(reader[4].ToString());
listOfOrderList.Add(new OrderList()
{
serialNumber = ++sno,
orderID = (int)reader[0],
productID = (int)reader[2],
quantity = (int)reader[3],
price = price,
productName = reader[5].ToString(),
});
}
connection.Close();
}
return listOfOrderList;
In your case its best to change the method signature to use an IList instead of List
public IList<OrderList> GetOrderList(OrderList orderList)
{
//get your data and build your list here
return new List<OrderList>();
}
See the differences between ICollection and IList in this answer
The answer is right there in the FxCop message. Just change the return type to be ICollection<OrderList>, like so:
public ICollection<OrderList> GetOrderList(OrderList orderList)
{
...
return new List<OrderList>();
}
I have the following classes:
public class Products
{
public int Id { get; set; }
public string ProductName { get; set; }
public int Price { get; set; }
public IList<ProductFiles> ProductFiles { get; set; }
}
public class ProductFiles
{
public int NumberOfFiles { get; set; }
public int NumberOfShops { get; set; }
}
Here I am trying to set the value of the property NumberOfFiles (member of ProductFiles):
public Products CountProductFiles(int productId)
{
DB_utilities db = new DB_utilities();
object[] spParams = new object[] { productId};
Products product = new Products();
using (var reader = db.procSelect("[Products_CountFiles]", spParams))
{
reader.Read();
{
Products _products = new Products
{
ProductName = (string)reader["ProductName"],
Price = (double)reader["Price"],
// I am trying to do something like this but this does not work:
ProductFiles.NumberOfFiles = (int)reader["NumberOfFiles"]
};
Products = _products ;
}
}
return Products;
}
How can I set the value of the prop NumberOfFiles? Or is the entire concept wrong?
As ProductFiles is a collection of ProductFiles, you need to do this
Products p = new Products();
p.ProductFiles = new List<ProductFiles>();
p.ProductFiles.Add(new ProductFiles() { NumberOfFiles = 1 }); // or some other defined value.
The collection needs to be initialized before adding objects to it.
In your example, you do not treat ProductFiles as a collection, that is why you get the error.
The point of a collection is that it can contain zero or more items. You need to put an instance in the collection. You also need to create a collection to ensure that the collection itself is not null.
new Product {
Files = new List<ProductFile>() {
new ProductFile {
FileCount = 42
}
}
}
In this example, Products::ProductFiles is a list.
Hence, in order to set the value of NumberOfFiles, do something like this:
ProductFiles[i].NumberOfFiles = //whatever you want to set it to.
But, before doing all this, do not forget to instantiate the List variable. Otherwise, it will itself be NULL.