Reputation: 958
I have two objects of type ProductInformation
, which contains properties for productId, productName, and price. I also have a method that queries a database for this information to populate the product class.
ProductInformation giftcard = query.ExecuteQuery(10) //this returns a giftcard
ProductInformation giftCertificate = query.ExecuteQuery(9) //this returns a gift certificate
I have stepped through the queries, and can confirm that, after running the first line, the gift card is successfully populated. However, somehow, after I create the gift certificate, it overwrites the gift card object with the properties from the gift certificate. To my understanding, they should be seperate objects. What am I missing so that I can keep the gift card?
For reference, the queries I'm using are essentially
SELECT *
FROM Products
WHERE ProductName like '%gift card'
And
SELECT *
FROM Products
WHERE ProductName like '%gift certificate'
The only thing I can think of is that my query class has a private ProductInformation object that I'm using to return to the giftcard and giftcertificate like
ProductInformation thisProduct;
public ProductInformation ExecuteQuery(int i)
{
switch (i)
case 10:
thisProduct = GiftCard();
break;
case 9:
thisProduct = GiftCertificate();
break;
return thisProduct;
}
private ProductInformation GiftCard()
{
using (SqlConnection con = new SqlConnection(conectionString))
{
con.Open();
return con.query<ProductInformation>(giftCardQuery).First();
}
}
private ProductInformation GiftCertificate()
{
using (SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
return con.query<ProductInformation>(giftCertQuery).First();
}
}
but since I'm assigning thisProduct to local variables in my test method, that should create new instances of the class, right?
Upvotes: 0
Views: 996
Reputation: 8502
To expand on other answers, ProductInformation
is a reference type and reference types are always passed By Reference.
Moreover, if you declare it at class level, same instance will be returned by both the calls, further to that the calling code receives the same instance of ProductInformation object
as its declared at class level and same query
object is used in both the method calls.
So, idea to use separate instances of ProductInformation object would be achieved if you move that variable to inside those methods, so it will be destroyed when the method call exits and recreated when next method call starts.
More info on memory management, refernce and value types is on Eric Lippert's blog:
Upvotes: 0
Reputation: 17010
Part of the problem here is the use of LINQ. The execution is deferred until use. What this means is the object may not be changing, per se, it just may have never been set until you query it.
Regardless, the pattern you are using is rather strange. Why didn't you opt for a more repository focused data access methodology. It is much cleaner than funneling everything through a quasi-singleton to get data. It is also a better separation of concerns.
@TMKeown has an interesting solution that will likely solve the immediate concern, but as an architect, I would be more concerned with the way you have set to solve the problem. Why are you funneling things through in this manner. If there is a good motivation, there should be a pattern that keeps the motivation without carrying forward the problems associated (one object magically becomes another).
Upvotes: 0
Reputation: 419
Both giftcard and giftCertificate the same instance and the second statement just changes the existing object. I guess putting
thisProduct = new ProductInformation();
before switch statement in ExecuteQuery method should help. Also it look like that the thisProduct shouldn't be on class level scoped.
ProductInformation thisProduct;
public ProductInformation ExecuteQuery(int i)
{
thisProduct = new ProductInformation();
switch (i)
case 10:
thisProduct = GiftCard();
break;
case 9:
thisProduct = GiftCertificate();
break;
return thisProduct;
}
Upvotes: 1
Reputation: 700382
"since I'm assigning thisProduct to local variables in my test method, that should create new instances of the class, right?"
No, assigning a reference doesn't automatically create a new instance.
If you use the same object for reading from the database, and then assign that object to a variable in the hope that it will create a separate instance, then that is the problem. You will just end up with two references to the same object, so when you read data for the next object into it, it will overwrite the previous data.
You should create a new instance for each object that you want to read.
Upvotes: 3
Reputation: 12857
Doesn't look like a local variable:
ProductInformation thisProduct;
ExecuteQuery(int i)
{
switch (i)
case 10:
thisProduct = GiftCard();
break;
case 9:
thisProduct = GiftCertificate();
break;
return thisProduct;
}
Your Query
class is being used to load both, and the query object is referencing the same ProductInformation instance. You have 2 options in my opinion:
-Use 2 query
instances, because your query class has state (bad idea).
-Move your ProductInformation
thisProduct variable inside the ExecuteQuery()
method.
Upvotes: 2