I'm trying to do some refactoring on a project. I want to replace the code between the lines and with the two commented lines above it so I can use it on another page where I need the quote object
//quote.LoadActive();
//QuoteID = quote.Id;
//--------------------------------------------------------
List<Quote> DBquotes = session.Query<Quote>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.ToList();
foreach (Quote q in DBquotes)
{
if (q.IsActive)
{
QuoteID = q.Id;
quote = session.Load<Quote>(q.Id);
}
}
//--------------------------------------------------------
Here's the LoadActive() function inside the Quote class
public Quote LoadActive()
{
List<Quote> DBquotes = session.Query<Quote>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.ToList();
foreach (Quote q in DBquotes)
if (q.IsActive)
return session.Load<Quote>(q.Id);
return new Quote();
}
But I don't know how to actually update the quote object. I can't update inside the function without doing it element by element and that's too tedious. If I try and do quote = quote.LoadActive() then it complains that quote hasn't been initialized. I'm sure there's a way to set up what I'm trying to do but I'm blanking and can't think of good keywords to google my question. I couldn't even come up with a good subject wording for this post!
EDIT: tl;dr I need to load the active quote into the 'quote' object to be used by the page. What's in between the lines works, I want to replace all with the commented lines above (or something similar).
You're Quote object should not be responsible for accessing the database. You should be using some Data Access class or even better yet, a Query Handler to access the DB.
I think you might be a little confused as to what the code is doing. Let me try to explain.
public Quote LoadActive()
{
//This call returns every Quote Document in the DB
//RavenDB by default will only return a Max of 128 w/out doing paging
List<Quote> DBquotes = session.Query<Quote>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.ToList();
//This doesn't make any sense. You're saying the first quote that is active,
//make another expensive DB call and return the same object.
//I still don't know what you want to do, but you already have the quote object
//why would you go to the DB and get something that you already have?
foreach (Quote q in DBquotes)
if (q.IsActive)
return session.Load<Quote>(q.Id);//Unnecessary, you have the Quote already
//return q;
return new Quote(); //if there's no active quotes just return an Empty Quote Object
}
Are you trying to return all Active Quotes from the DB?
You can do this
var activeQuotes = session.Query<Quote>()
.Where(x => x.IsActive == true)
.ToList();//Remember, RavenDB's safe by default feature
//will only return 128 records, you have to
//implement paging
If you are trying to just return the first IsActive quote (which is what it looks like you want to do from your code) you can simply do:
public Quote LoadActive()
{
return session.Query<Quote>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.FirstOrDefault(x => x.IsActive);
}
Edit based on comment:
This will allow you to accomplish what you want by
QuoteId = quote.LoadActive().Id;
Related
I receive the following error when I try to run my code. I haven't managed to solve it yet, please Help:
edit: Marked with * where it fails.
>
public IQueryable<Video> GetVideos([QueryString("id")] int? categorieId)
{
var _db = new TeleviziuneAcademicaAspSilverlight.Models.VideoContext();
IQueryable<Video> query = *_db.Videos;*
if (categorieId.HasValue && categorieId > 0)
{
query = query.Where(v => v.CategorieID == categorieId);
}
return query;
Change
IQueryable<Video> query =
to
IQueryable<Appname.Models.Video> query =
The reason for your error is that you have the type Video defined twice and because of using a short type name you accidentally reference not the one Video you should.
Also change it in the method's return value
public IQueryable<Appname.Models.Video> GetVideos( ... )
You seem to have two classes called Video. If you need both, you'll need to project from one to the other before your return statement:
return query.Select(dbVideo => new Appname.Video()
{
Prop1 = dbVideo.Prop1,
Prop2 = dbVideo.Prop2,
// etc.
});
Though you'll probably need to change the return type to an IEnumerable<> if you do that.
If you can just work with Appname.Models.Video, change IQueryable<Video> to IQueryable<Appname.Models.Video> in the method signature and the method body.
I feel like I must be doing this wrong. I've got a function that is supposed to construct a query based on an API's description of available fields. Here's what I've got:
var query_fields = getQueryFieldsFor(sobject_name);
// Need query fields for the next statement, which actually does the query
public function getQueryFieldsFor(sObject:String):String{
//helper function to get queryfields for given sobject
var queryFields:String = '';
app.connection.describeSObject(sObject,
new mx.rpc.Responder(
function(result:DescribeSObjectResult):void{
var returnFields:String = '';
for ( var field:Field in result.fields ){
if(field.active){
returnFields.concat(field.name+',')
}
}
returnFields.slice(0, returnFields.length-1); //remove last comma
queryFields = returnFields;
}, function(error):void{
Alert.show('error in getQueryFieldsFor function');
})
);
return queryFields;
}
I know this doesn't work, and I think I understand why. However, I keep running into this type of issue and I believe I'm just thinking about it/designing it wrong. So what's a better pattern here? Would really appreciate any insight on this. Many thanks in advance.
It would be better to externalize your functions and execute your next line of code after the fact:
public function getQueryFieldsFor(sObject:String):String
{
var responder:Responder = new Responder( onResult, onFault);
app.connection.describeSObject(sObject, responder);
}
private function onResult(result:DescribeSObjectResult):void
{
var returnFields:String = '';
for ( var field:Field in result.fields ){
if(field.active){
returnFields.concat(field.name+',')
}
}
returnFields.slice(0, returnFields.length-1); //remove last comma
queryFields = returnFields;
}
Your main problem though is not the code, but a lack of thinking asynchronously. You cannot have a function called "getQueryFields" that will return it instantly. What you want to do is think in the request/response way. You're trying to get some data, a request is made to a service, gets the data back, updates a property which is then binded to a view which gets redrawn. This is the proper way to do any webapp.
It might be beneficial for you to also look at application frameworks like RobotLegs and Parsley since it helps you manage these situations. Parsley also has a task library which lets you perform several asynchronous task one after another.
I have two tables without any cascade deleting. I want to delete parent object with all child objects. I do it this way
//get parent object
return _dataContext.Menu.Include("ChildMenu").Include("ParentMenu").Include("Pictures").FirstOrDefault(m => m.MenuId == id);
//then i loop all child objects
var picList = (List<Picture>)menu.Pictures.ToList();
for (int i = 0; i < picList.Count; i++)
{
if (File.Exists(HttpContext.Current.Server.MapPath(picList[i].ImgPath)))
{
File.Delete(HttpContext.Current.Server.MapPath(picList[i].ImgPath));
}
if (File.Exists(HttpContext.Current.Server.MapPath(picList[i].ThumbPath)))
{
File.Delete(HttpContext.Current.Server.MapPath(picList[i].ThumbPath));
}
//**what must i do here?**
//menu.Pictures.Remove(picList[i]);
// DataManager dm = new DataManager();
// dm.Picture.Delete(picList[i].Id);
//menu.Pictures.de
//_dataContext.SaveChanges();
//picList[i] = null;
}
//delete parent object
_dataContext.DeleteObject(_dataContext.Menu.Include("ChildMenu").Include("ParentMenu")
.Include("Pictures").FirstOrDefault(m => m.MenuId == id););
_dataContext.SaveChanges();
It is enough to set the <OnDelete Action="Cascade" /> for the master association end in the CSDL part of the model.
In this case your code will work.
My situation was slightly different, and it took a while to get it right so I thought it worth documenting. I have two related tables, Quote and QuoteExtension:
Quote (Parent, Primary Key QuoteId)
QuoteExtension (Calculated fields for Quote, Primary and Foreign Key QuoteId)
I didn't have to set the OnDelete action to get it to work - but Craig's comment (if I could vote that up more I would!) led me to discover the issue. I was attempting to delete the Quote when QuoteExtension was not loaded. Therefore I found two ways that worked:
var quote = ent.Quote.Include("QuoteExtension").First(q => q.QuoteId == 2311);
ent.DeleteObject(quote);
ent.SaveChanges();
Or:
var quote = ent.Quote.First(q => q.QuoteId == 2311);
if (quote.QuoteExtension != null)
ent.Refresh(RefreshMode.ClientWins, quote.QuoteExtension);
ent.DeleteObject(quote);
ent.SaveChanges();
Interestingly trying to delete QuoteExtension manually didn't work (although it may have if I had included ent.SaveChanges() in the middle - this tends to happen only at the end of a unit of work in this system so I wanted something that didn't rely on this.
Is it possible to clear a Flex flash.utils.Dictionary? I have a Dictionary that I want to clear (remove all elements).
I don't believe there is an explicit clear command.
However, you could write your own that would loop through all the keys and run this
delete dict[key];
Or you can just reassign
dict = new Dictionary()
I think this will work, but I'm not 100% sure, as you're modifying the dictionary while iterating over it:
function clear(d:Dictionary):void {
for(var id:* in d) {
delete d[id];
}
}
However, I generally just create a new Dictionary whenever I need to clear one (though if it's referenced in multiple places then that might not work for you).
To remove all the elements in the Dictionary, loop through each key and use the delete keyword
function clear(dict:Dictionary):void
{
for(var key:Object in dict)
{
delete dict[key];
}
}
If you want to be 100% sure that your deleted keys are garbage collected, you must replace your Dictionary instance with a new Dictionary.
dict = new Dictionary();
I once had a Dictionary object with 3 million Strings as keys. Those Strings would only be garbage collected when the Dictionary instance itself was.
Not only do you need to make sure the key is of type object or * you need to get the keys first then delete them from the dictionary. Otherwise you will end up one key left in the dictionary(the last one).
I remember the above code working before but recently that has changed with the last iteration of flash player.
This code will ensure they are all removed including the last one.
//Clean up the dictionary
var keys:Array = [];
var key:*;
for ( var key:* in dictionary )
keys.push( key );
for each ( var key:* in keys )
delete dictionary[ key ];
Just:
dictionary = new Dictionary()
public static function clear(dict:Dictionary):void {
var key:*
for(key in dict) {
delete dict[key];
}
}
Use the above function as a utility function and you can use it throughout your code base.
OK I am looping through the properties in an object like so:
private var _propsList:Object = {'Type':'product_type'
,'Kind':'product_type_sub'
,'Stone':'primary_stone'
,'Stone Color':'primary_stone_sub'
,'Metal':'metal_type'
,'Brand':'product_brand'};
for(key in _propsList)
{
val = _propsList[key];
trace(key +" = "+ val);
}
I am expecting the first trace to be Type = property_type since that is the first one defined in the array, however it is coming up random everytime. I guess this is because my keys are strings and not integers, however is there a way to specify the order it loops through them?
Thanks!!
You can't rely on for (v in someObject) ... to return things in a predictable order, no.
Depending on your specific situation, you could just use an array to hold the keys, and just iterate through that:
private var keys:Array = ["Type", "Kind", "Stone", "Stone Color", "Metal", "Brand"];
private function iterate():void
{
for each (var k:String in keys)
{
trace(_propsList[k]);
}
}
Maybe a bit obvious or non-elegant, but it'd get the job done. :)
you could hack it by classing-out your "_propsList" object creating an array inside of the newly created PropsList class that references the properties in order. At that point, you could run a FOR loop on the array and get your properties in order.
OR, you could have a function inside that new class that would return an Array of those properties. like this:
public function getProps():Array {
return [myPropertyOne, myPropertyTwo, myPropertyThree];
}
In general, I think this is a case where you shouldn't depend on a particular behavior from the framework/language you are using. This type of behavior is generally poorly documented and can change from version to version.
If you really need a specific retrieval order, I would create a wrapper class as jevinkones suggested above. Maybe there's even a utility class in the framework somewhere to accomplish this (Dictionary, etc.?)
HTH,
Karthik
I found this link that gives some background:
Subtle Change in for..in Loops for ActionScript 3
This question is actually a dup of this one.
How about using an array representation like this:
var _propsList:Array = [
['Type', 'product_type'],
['Kind', 'product_type_sub'],
['Stone', 'primary_stone'],
['Stone Color', 'primary_stone_sub'],
['Metal', 'metal_type'],
['Brand', 'product_brand']
];
for(var i in _propsList) {
var elem = _propsList[i];
var key = elem[0];
var val = elem[1]
}