Reduce massive includes in EF - entity-framework

Any ways to shorten this include statement?
var query = Context.Businesses
.Include(b => b.Categories)
.Include(b => b.Branches.Select(br => br.Address))
.Include(b => b.Branches.Select(br => br.BranchType))
.Include(b => b.Branches.Select(br => br.CustomFields))
.Include(b => b.Branches.Select(br => br.Phones))
.Include(b => b.Branches.Select(br => br.OpeningTimes.Select(ot => ot.WorkingPeriods)));
I thought about using a SPROC but I'm unsure how it will know what was returned.
So is there a non hard-coded way to do this shorter than it is? Perhaps an external lambda that treats all the properties of Branch?

You could do something similar to the answer to this question. So in your case, make an extension method like this:
public static class DataContextExtensions
{
public static IQueryable<Business> BusinessesComplete(this DataContext context){
return context.Businesses
.Include(b => b.Categories)
.Include(b => b.Branches.Select(br => br.Address))
.Include(b => b.Branches.Select(br => br.BranchType))
.Include(b => b.Branches.Select(br => br.CustomFields))
.Include(b => b.Branches.Select(br => br.Phones))
.Include(b => b.Branches.Select(br => br.OpeningTimes.Select(ot => ot.WorkingPeriods)));
}
}
Then use it like this:
Business business = context.BusinessesComplete().Where(b => ...etc);

Related

Scala patternmatching

I have following code for pattern matching in Scala:
response.flatMap(employee =>
employee match {
case e if e.type == Manager => e.headoffice
case e if e.type == Clerk => e.branch
case _ => None
}
)
Is this optimum way of doing pattern matching? Can it be made more concise?
You can try matching on type:
response.flatMap(e => e.type match {
case Manager => e.headoffice
case Clerk => e.branch
case _ => None
})
I personally would do it like this:
response.map(e => e -> e.`type`).flatMap {
case (e, Manager) => e.headoffice
case (e, Clerk) => e.branch
case _ => None
}

Not getting exact result from query execute

I'm using CodeIgniter with MongoDB and want to fetch a data using id which saves in MongoDB I execute a query which prints data but I don't understand what data is print
I Execute this query
$query=$this->mongo_db->where('posts', array('_id' => new \MongoDB\BSON\ObjectID($id)));
and Get This result not any data
Mongo_db Object
(
[CodeIgniter:Mongo_db:private] => User Object
(
[benchmark] => CI_Benchmark Object
(
[marker] => Array
(
[total_execution_time_start] => 1559113613.9923
[loading_time:_base_classes_start] => 1559113613.9923
[loading_time:_base_classes_end] => 1559113614.0023
[controller_execution_time_( User / single )_start] => 1559113614.0023
)
)
[hooks] => CI_Hooks Object
(
[enabled] =>
[hooks] => Array
(
)
[_objects:protected] => Array
(
)
[_in_progress:protected] =>
)
[config] => CI_Config Object
(
[config] => Array
(
[base_url] => http://localhost/chronicle/
[index_page] => index.php
[uri_protocol] => REQUEST_URI
[url_suffix] =>
[language] => english
[charset] => UTF-8
[enable_hooks] =>
[subclass_prefix] => MY_
[composer_autoload] =>
[permitted_uri_chars] => a-z 0-9~%.:_\-
[enable_query_strings] =>
[controller_trigger] => c
[function_trigger] => m
[directory_trigger] => d
[allow_get_array] => 1
[log_threshold] => 0
[log_path] =>
[log_file_extension] =>
[log_file_permissions] => 420
[log_date_format] => Y-m-d H:i:s
[error_views_path] =>
[cache_path] =>
[cache_query_string] =>
[encryption_key] =>
[sess_driver] => files
[sess_cookie_name] => ci_session
[sess_expiration] => 7200
[sess_save_path] =>
[sess_match_ip] =>
[sess_time_to_update] => 300
[sess_regenerate_destroy] =>
[cookie_prefix] =>
[cookie_domain] =>
[cookie_path] => /
[cookie_secure] =>
[cookie_httponly] =>
[standardize_newlines] =>
[global_xss_filtering] =>
[csrf_protection] =>
[csrf_token_name] => csrf_test_name
[csrf_cookie_name] => csrf_cookie_name
[csrf_expire] => 7200
[csrf_regenerate] => 1
[csrf_exclude_uris] => Array
(
)
[compress_output] =>
[time_reference] => local
[rewrite_short_tags] =>
[proxy_ips] =>
[mongo_db] => Array
(
[active_config_group] => default
[default] => Array
(
[settings] => Array
(
[auth] => 1
[debug] => 1
[return_as] => array
[auto_reset_query] => 1
)
[connection_string] =>
[connection] => Array
(
[host] => 127.0.0.1
[port] => 27017
[user_name] => admin
[user_password] => admin
[db_name] => centralchronicle
[db_options] => Array
(
)
)
[driver] => Array
(
)
)
)
)
[is_loaded] => Array
(
[0] => D:\xampp\htdocs\chronicle\application\config/mongo_db.php
)
[_config_paths] => Array
(
[0] => D:\xampp\htdocs\chronicle\application\
)
)
[log] => CI_Log Object
(
[_log_path:protected] => D:\xampp\htdocs\chronicle\application\logs/
[_file_permissions:protected] => 420
[_threshold:protected] => 0
[_threshold_array:protected] => Array
(
)
[_date_fmt:protected] => Y-m-d H:i:s
[_file_ext:protected] => php
[_enabled:protected] => 1
[_levels:protected] => Array
(
[ERROR] => 1
[DEBUG] => 2
[INFO] => 3
[ALL] => 4
)
)
[utf8] => CI_Utf8 Object
(
)
[uri] => CI_URI Object
(
[keyval] => Array
(
)
[uri_string] => User/single/5ced0e57ed4e3e0fbc017e19
[segments] => Array
(
[1] => User
[2] => single
[3] => 5ced0e57ed4e3e0fbc017e19
)
[rsegments] => Array
(
[1] => User
[2] => single
[3] => 5ced0e57ed4e3e0fbc017e19
)
[_permitted_uri_chars:protected] => a-z 0-9~%.:_\-
[config] => CI_Config Object
(
[config] => Array
(
[base_url] => http://localhost/chronicle/
[index_page] => index.php
[uri_protocol] => REQUEST_URI
[url_suffix] =>
[language] => english
[charset] => UTF-8
[enable_hooks] =>
[subclass_prefix] => MY_
[composer_autoload] =>
[permitted_uri_chars] => a-z 0-9~%.:_\-
[enable_query_strings] =>
[controller_trigger] => c
[function_trigger] => m
[directory_trigger] => d
[allow_get_array] => 1
[log_threshold] => 0
[log_path] =>
[log_file_extension] =>
[log_file_permissions] => 420
[log_date_format] => Y-m-d H:i:s
[error_views_path] =>
[cache_path] =>
[cache_query_string] =>
[encryption_key] =>
[sess_driver] => files
[sess_cookie_name] => ci_session
[sess_expiration] => 7200
[sess_save_path] =>
[sess_match_ip] =>
[sess_time_to_update] => 300
[sess_regenerate_destroy] =>
[cookie_prefix] =>
[cookie_domain] =>
[cookie_path] => /
[cookie_secure] =>
[cookie_httponly] =>
[standardize_newlines] =>
[global_xss_filtering] =>
[csrf_protection] =>
[csrf_token_name] => csrf_test_name
[csrf_cookie_name] => csrf_cookie_name
[csrf_expire] => 7200
[csrf_regenerate] => 1
[csrf_exclude_uris] => Array
(
)
[compress_output] =>
[time_reference] => local
[rewrite_short_tags] =>
[proxy_ips] =>
[mongo_db] => Array
(
[active_config_group] => default
[default] => Array
(
[settings] => Array
(
[auth] => 1
[debug] => 1
[return_as] => array
[auto_reset_query] => 1
)
[connection_string] =>
[connection] => Array
(
[host] => 127.0.0.1
[port] => 27017
[user_name] => admin
[user_password] => admin
[db_name] => centralchronicle
[db_options] => Array
(
)
)
[driver] => Array
(
)
)
)
)
[is_loaded] => Array
(
[0] => D:\xampp\htdocs\chronicle\application\config/mongo_db.php
)
[_config_paths] => Array
(
[0] => D:\xampp\htdocs\chronicle\application\
)
)
)
[router] => CI_Router Object
(
[config] => CI_Config Object
(
[config] => Array
(
[base_url] => http://localhost/chronicle/
[index_page] => index.php
[uri_protocol] => REQUEST_URI
[url_suffix] =>
[language] => english
[charset] => UTF-8
[enable_hooks] =>
[subclass_prefix] => MY_
[composer_autoload] =>
[permitted_uri_chars] => a-z 0-9~%.:_\-
[enable_query_strings] =>
[controller_trigger] => c
[function_trigger] => m
[directory_trigger] => d
[allow_get_array] => 1
[log_threshold] => 0
[log_path] =>
[log_file_extension] =>
[log_file_permissions] => 420
[log_date_format] => Y-m-d H:i:s
[error_views_path] =>
[cache_path] =>
[cache_query_string] =>
[encryption_key] =>
[sess_driver] => files
[sess_cookie_name] => ci_session
[sess_expiration] => 7200
[sess_save_path] =>
[sess_match_ip] =>
[sess_time_to_update] => 300
[sess_regenerate_destroy] =>
[cookie_prefix] =>
[cookie_domain] =>
[cookie_path] => /
[cookie_secure] =>
[cookie_httponly] =>
[standardize_newlines] =>
[global_xss_filtering] =>
[csrf_protection] =>
[csrf_token_name] => csrf_test_name
[csrf_cookie_name] => csrf_cookie_name
[csrf_expire] => 7200
[csrf_regenerate] => 1
[csrf_exclude_uris] => Array
(
)
[compress_output] =>
[time_reference] => local
[rewrite_short_tags] =>
[proxy_ips] =>
[mongo_db] => Array
(
[active_config_group] => default
[default] => Array
(
[settings] => Array
(
[auth] => 1
[debug] => 1
[return_as] => array
[auto_reset_query] => 1
)
[connection_string] =>
[connection] => Array
(
[host] => 127.0.0.1
[port] => 27017
[user_name] => admin
[user_password] => admin
[db_name] => centralchronicle
[db_options] => Array
(
)
)
[driver] => Array
(
)
)
)
)
[is_loaded] => Array
(
[0] => D:\xampp\htdocs\chronicle\application\config/mongo_db.php
)
[_config_paths] => Array
(
[0] => D:\xampp\htdocs\chronicle\application\
)

Splitting an overlong IIncludableQueryable<>

I have a fairly complex data model with some 30-odd tables. I'm working on a Web API to provide data to an Angular 2 front-end, and found that it would be easiest to download a "whole" item with all its subclasses in one go, considering that this doesn't involve much data.
However, I'm now looking at the following monstrosity:
var query = context.GlobalBcf
.Include(x => x.Location)
.Include(x => x.RadioEquipment.Model)
.Include(x => x.RadioEquipment.RadioEquipmentSuppliers).ThenInclude(x => x.Supplier)
.Include(x => x.RadioEquipment.RadioEquipmentTypes).ThenInclude(x => x.Type)
.Include(x => x.GlobalBcfPowerSupplies).ThenInclude(x => x.PowerSupply)
.Include(x => x.GlobalBcfApplications).ThenInclude(x => x.Application)
.Include(x => x.OvtpType)
.Include(x => x.BatteryType)
.Include(x => x.AmountBattery)
.Include(x => x.Bcfs)
.Include(x => x.Bcfs).ThenInclude(x => x.Mode)
.Include(x => x.Bcfs).ThenInclude(x => x.TrxSigBw1)
.Include(x => x.Bcfs).ThenInclude(x => x.TrxSigBw2)
.Include(x => x.Bcfs).ThenInclude(x => x.TrxSigBw3)
.Include(x => x.Bcfs).ThenInclude(x => x.TrxSigBw4)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment).ThenInclude(x => x.Btses)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.ExternalComponent)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.Type)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.FrequenceRepeaters).ThenInclude(x => x.Model)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.FrequenceRepeaters).ThenInclude(x => x.Supplier)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.Model)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.PowerSupply)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.Supplier)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.OpticRepeaters).ThenInclude(x => x.OtrxModel)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.OpticRepeaters).ThenInclude(x => x.RuModel)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.OpticRepeaters).ThenInclude(x => x.RuPowerSupply)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.OpticRepeaters).ThenInclude(x => x.RuMode)
.AsQueryable();
return query.Single(x => x.Id == message.Id);
This is obviously becoming hard to maintain, so I'm wondering whether it wouldn't be possible to split this up into smaller, easier to maintain pieces which don't repeat the same over and over:
.Include(x => x.Bcfs)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits)
.Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.OpticRepeaters).
Any tips, pointers, ideas?
I have found a solution by just splitting pieces of code into different extension:
class SupraBigZone {
public List<Zone> Zones {get; set;}
}
class Zone {
public SupraBigZone SupraBigZone {get; set;}
public List<SmallZone> SmallZones {get; set;}
}
class SmallZone {
public Zone Zone {get; set;}
}
And then you have a class containing a SupraBigZone:
class Game {
public SupraBigZone GameZone {get; set;}
public OtherProperty OtherProperty {get; set;}
}
public static class IQueryableExtensions
{
public static IIncludableQueryable<T, Zone> IncludeSupraBigZone<T>(this IQueryable<T> values, Func<T,SupraBigZone> getSupraBigZone) where T : class
{
return values
.Include(c => getSupraBigZone(c)).ThenInclude(h => h.Zones).ThenInclude(z => z.SupraBigZone)
.Include(c => getSupraBigZone(c)).ThenInclude(h => h.Zones).ThenInclude(z => z.SmallZones).ThenInclude(s => s.Zone);
}
}
Note that the extension takes Zone as second generic type, this is because in this example, the very last include includes a Zone.
In your DbContext, you can use it as follows:
public DbSet<Game> Games { get; set; }
public IQueryable<Car> GameWithDependencies
{
get
{
return
Games
.IncludeSupraBigZone(g => g.GameZone)
.Include(g => g.OtherProperty);
}
}

Express Checkout with Paypal's PHP API cannot checkout without account

I'm trying to test "Pay Without a Paypal Account" using a SetExpressCheckout call from Paypal's PHP api, but the Paypal page I'm directed to only has the options to pay with an account or create an account - there is no option to pay without an account.
I've configured the sandbox seller account I'm testing with to not require users to have accounts using the instructions here: https://www.paypal-community.com/t5/Merchant-services-Archive/Paypal-account-optional/td-p/233270
Here's a printout of the setECReq object just before I call the $paypalService->SetExpressCheckout() method:
PayPal\PayPalAPI\SetExpressCheckoutReq Object
(
[SetExpressCheckoutRequest] => PayPal\PayPalAPI\SetExpressCheckoutRequestType Object
(
[SetExpressCheckoutRequestDetails] => PayPal\EBLBaseComponents\SetExpressCheckoutRequestDetailsType Object
(
[OrderTotal] =>
[ReturnURL] => (stack overflow won't let me post links)/dg/cart/checkout/paypal/express/review
[CancelURL] => (stack overflow won't let me post links)/dg/cart/checkout/paypal/express/cancel
[TrackingImageURL] =>
[giropaySuccessURL] =>
[giropayCancelURL] =>
[BanktxnPendingURL] =>
[Token] =>
[MaxAmount] =>
[OrderDescription] =>
[Custom] =>
[InvoiceID] =>
[ReqConfirmShipping] => 0
[ReqBillingAddress] =>
[BillingAddress] =>
[NoShipping] => 0
[AddressOverride] => 0
[LocaleCode] =>
[PageStyle] =>
[cppheaderimage] =>
[cppheaderbordercolor] => 000000
[cppheaderbackcolor] => 000000
[cpppayflowcolor] => 00FF00
[cppcartbordercolor] => EEEEEE
[cpplogoimage] => (stack overflow won't let me post links)/dg/assets/img/paypal_logo2.gif
[Address] =>
[PaymentAction] =>
[SolutionType] =>
[LandingPage] =>
[BuyerEmail] =>
[ChannelType] =>
[BillingAgreementDetails] => Array
(
[0] => PayPal\EBLBaseComponents\BillingAgreementDetailsType Object
(
[BillingType] => MerchantInitiatedBillingSingleAgreement
[BillingAgreementDescription] => The customer pays for the products, and buyer sends them.
[PaymentType] =>
[BillingAgreementCustom] =>
)
)
[PromoCodes] =>
[PayPalCheckOutBtnType] =>
[ProductCategory] =>
[ShippingMethod] =>
[ProfileAddressChangeDate] =>
[AllowNote] => 1
[FundingSourceDetails] =>
[BrandName] => Dusty Gamble | Glass Art
[CallbackURL] =>
[EnhancedCheckoutData] =>
[OtherPaymentMethods] =>
[BuyerDetails] =>
[PaymentDetails] => Array
(
[0] => PayPal\EBLBaseComponents\PaymentDetailsType Object
(
[OrderTotal] => PayPal\CoreComponentTypes\BasicAmountType Object
(
[currencyID] => USD
[value] => 45.00
)
[ItemTotal] => PayPal\CoreComponentTypes\BasicAmountType Object
(
[currencyID] => USD
[value] => 42.00
)
[ShippingTotal] => PayPal\CoreComponentTypes\BasicAmountType Object
(
[currencyID] => USD
[value] => 3.00
)
[HandlingTotal] => PayPal\CoreComponentTypes\BasicAmountType Object
(
[currencyID] => USD
[value] => 0.00
)
[TaxTotal] =>
[OrderDescription] =>
[Custom] =>
[InvoiceID] =>
[ButtonSource] => PayPal_SDK
[NotifyURL] =>
[ShipToAddress] =>
[MultiShipping] =>
[FulfillmentReferenceNumber] =>
[FulfillmentAddress] =>
[PaymentCategoryType] =>
[ShippingMethod] =>
[ProfileAddressChangeDate] =>
[PaymentDetailsItem] => Array
(
[0] => PayPal\EBLBaseComponents\PaymentDetailsItemType Object
(
[Name] => Object #883 - Synapse
[Number] =>
[Quantity] => 1
[Tax] =>
[Amount] => PayPal\CoreComponentTypes\BasicAmountType Object
(
[currencyID] => USD
[value] => 42.00
)
[EbayItemPaymentDetailsItem] =>
[PromoCode] =>
[ProductCategory] =>
[Description] =>
[ItemWeight] =>
[ItemLength] =>
[ItemWidth] =>
[ItemHeight] =>
[ItemURL] =>
[EnhancedItemData] =>
[ItemCategory] => Physical
)
)
[InsuranceTotal] => PayPal\CoreComponentTypes\BasicAmountType Object
(
[currencyID] => USD
[value] => 0.00
)
[ShippingDiscount] =>
[InsuranceOptionOffered] =>
[AllowedPaymentMethod] =>
[EnhancedPaymentData] =>
[SellerDetails] =>
[NoteText] =>
[TransactionId] =>
[PaymentAction] => Sale
[PaymentRequestID] =>
[OrderURL] =>
[SoftDescriptor] =>
[BranchLevel] =>
[OfferDetails] =>
[Recurring] =>
[PaymentReason] =>
)
)
[FlatRateShippingOptions] =>
[CallbackTimeout] =>
[CallbackVersion] =>
[CustomerServiceNumber] =>
[GiftMessageEnable] =>
[GiftReceiptEnable] =>
[GiftWrapEnable] =>
[GiftWrapName] =>
[GiftWrapAmount] =>
[BuyerEmailOptInEnable] =>
[SurveyEnable] =>
[SurveyQuestion] =>
[SurveyChoice] =>
[TotalType] =>
[NoteToBuyer] =>
[Incentives] =>
[ReqInstrumentDetails] =>
[ExternalRememberMeOptInDetails] =>
[FlowControlDetails] =>
[DisplayControlDetails] =>
[ExternalPartnerTrackingDetails] =>
[CoupledBuckets] =>
)
[DetailLevel] =>
[ErrorLanguage] =>
[Version] =>
)
)

Scala + Play Framework: Action composition explanation needed

This is the action composition taken from a sample that comes with the Play Framework
def IsAuthenticated(f: => String => Request[AnyContent] => Result) = Security.Authenticated(username, onUnauthorized) { user =>
Action(request => f(user)(request))
}
So, Security.Authenticated takes an username: RequestHeader => Option[String] and onAuthorized: RequestHeader=>SimpleResultand the second group of parantheses take String => Action[A]
And then in the controller I have:
def index = isAuthenticated { ...code }}
The code above is this, so I assume this is the f function => String => Request[AnyContent] => Result. Now, what I don't understand is what really happens here. I am not talking about User.findByEmail...., I'm talking about username => _ => .... What would the signature of this function look like if I called it directly?
username => _ =>
User.findByEmail(username).map { user =>
Ok(
html.dashboard(
Project.findInvolving(username),
Task.findTodoInvolving(username),
user
)
)
}.getOrElse(Forbidden)
If there was def isAuthenticated(f: => Request[AnyContent] => Result) I'd know how to use it and I'd understand it. But the extra "data" is confusing me.
UPDATE:
I guess I found something:
def f2: String => Int => List[Char] = x => _ => x.toList
And this would be called as:
f2("Andrew")(2) //there can be anything replacing 2 because I don't have access to it anyway
So the function above that I asked primarily about would be:
def f: => String => Request[AnyContent] => Result = username => _ => User.find.....
Am I right?
I get a "No by name parameter allowed here error".
If they don't use the second parameter why are they using String => Request => Result and not just simply String => Result?
That function definition is actually a curried function definition.
String => Request => Result actually means: f(s:String):(r:Request)=>Result ie a function that takes a String and returns a function that takes a Request and returns a Result.
Check out the part "Spicing up your functions": http://danielwestheide.com/blog/2013/01/30/the-neophytes-guide-to-scala-part-11-currying-and-partially-applied-functions.html
For me, the examples at https://github.com/mariussoutier/PlayBasics/tree/master/play-2.2-migration are very enlightening.