ict.ken.be

 

Posts in Category: Notes

Playstation 

Categories: Notes

Glossary

  • ELF: Extensible Linking Format is the file format commonly used for Playstation binaries. Eg. BOOT.ELF
  • ESR : This is not an abbriviation but a way to load dvd copies. I prefer using network loading with OPL as the whole point is to not only spare your dvd roms but also your playstation laser. Remeber that you need to patch your dvd iso before burning it.
  • FMCB : FreeMcBoot allows for booting your playstation into software installed onto your memory card. Which allows you to copy software from a usb-drive. It's kind of catch-22 as to be able to install the initial software on your memory card you need to have a card that has FMCB installed. If you can't buy an initial copy there are tricks to exploit the dvd loading and install it like this, but that's kind of tedious.
  • GSM : Graphics Synthetizer Mode Selector you might need to get some specific games working. You can learn about the workings, but it's mostly enough to just lookup the mode in the tables at PS2-home.
  • OPL : Open PS2 Loader, far the easiest way to manage playing games over the network. Doesn't work for all games, but use it whenever possible to spare your ps2 laser.
  • SMB : Server Message Block aka Samba allows you to setup a network between your PS2 and pc.
  • SMS : Simple Media System allows for playing videos. Nice, but not very useful since we all have tablets now.
  • MagicGate : Brand of original PS2 memory cards that is needed to run FMCB, watch out as often the bigger ones are fake and will not work. Use an original 8MB for your first experiments.
  • uLaunchElf : Your basic file browser that allows you to run executables.

Configuration

Some screenshots of playstation 2 fmcb and opl settings over network.

References

Entity Framework in the Enterprise - Notes 

Categories: EF Notes

by Julie Lerman

UI - Service Layer - Bus Layer - Repository/Unit of Work - Data Layer - Database

EF should stay in the data layer.
Split your context in smaller bounded contexts.

Bounded DbContext

  • Inspired on "Domain-Driven Design by Eric Evans" (domaindrivendesign.org)
  • All your navigation properties get pulled into the model.
  • Transition between context by id or by object.
  • Entity with property that is not persisted in the database: public decimal LineTotal { get; set; } ... In map class add Ignore(t => t.LineTotal)
  • Do not include navigation in the context: In OnModelCreating add modelBuilder.Ignore<T>();
  • Make sure non related is included: In OnModelCreating add modelBuilder.Entity<T>();
  • Migrations and creations: Add one model that includes all of your tables and use this one.
  • Put each context in it's own project.
  • Put the mappings also in their separated project. eg. BaseDataLayer - CompanyDatabaseInitializers - CustomerServiceBoundedContext - DataLayerMappings - DomainClasses - ReturnsBoundedContext - SalesBoundedContext
  • Use EF powertools to visualize your context and see what will be pulled in.
  • And then cherry pick what you need (eg. probably do not need the relationships)

Repositories and Unit of Work

  • Encapsulate Redundant Data Access Code
  • GetCustomerById(cid), GetAllCustomers, GetCurrentCustomers, GetLocalCustomers, GetFilteredCustomers
  • RemoveCustomer, AddCustomer

Install-Package entityframework
Install-Package t4scaffolding

scaffold repository DomainClasses.Customer -DbContextType:SalesContext

Always use ctx.Customers.Find(id) cause it will not roundtrip when not needed.

DbSet.Add(root) - All elements State=Added - Insert for each element, even if pre-existing in db
DbSet.Attach(root) - All elements State=Unchanged - Any new records with missing FKs will throw
Context.Entry(root).State=EntityState - Context attaches full graph, all entities State=Unchanged, Root (only) set to specific state - Any new with missing FKs will throw

Disconnected Graph
Attaching to Context: all new -> DbSet.Add(customer)
Root new, existing unchanged: Entry(customer).State=Added
Editing: Entry(customer).State=Modified then Entry(*each item*).State=Modified
Root edited and added: DbSet.Add(customer) then Entry(*each non added*).State=*correct state*

Make objects track their own state:
IObjectWithState
enum State { Added, Unchanged, Modified, Deleted }

public abstract class Person:IObjectWithState
[NotMapped]
public State State { get; set;}

Repository depends on the value of client-side State
Developer using repository MUST set client-side State!

StateHelpers - EntityState ConvertState(State state)
ContextHelpers - ApplyStateChanges(this DbContext context)

Difference between long running and short running context (or implement two repos)

Let repositories share the same context (Unit of work)
Move save method to unit of work
CustomerRepository contains Unit of work that contains a context

ReferencesContext
Especially when reading data: _context.Customers.AsNoTracking();

A DbSet represents the collection of all entities in the context, or that can be queried from the database, of a given type.
DbSet object are created from a DbContext using the DbContext.Set method
A DbContext instance represents a combination of the unit of work and repository patterns such that it can be used to query a database and group together changes that will then be written back to the store as a unit. DbContext is conceptually similar to ObjectContext.

  • Why build a repository on top op EF? EF is a repository!
  • Should you return an IQueryable from a repository
  • How much abstraction and refactoring? There will always be more.

Automated Testing Overview

  • Unit Testing
  • Integration Testing
  • Interaction Testing
  • System Testing
  • User Interface Testing

1. Complete model with Seed method
2. Initialize Database for each integration test
3. Use a testing database that can get destroyed frequently

Test your data annotations: test for DbEntityValidationException

Fake Context & Fake Data
IDbSet<TEntity> : DbQuery<TEntity>, IDbSet<TEntity>, IQueryable<TEntity>, IEnumerable<TEntity>, IQueryable, IEnumerable where TEntity : class

(you can also use IObjectSet)
public abstract class MyFakeDbSet<T> : IDbSet<T> where T : class, new()
{
}

Create implementation to override the find method

IUoW needs IContext

SalesPromotionAccessor (to hide the context and wrap it with your unit of work)

Building Data-Centric Single Apps with Breeze - Notes 

Categories: Javascript Notes

by Brian Noyes (brian.noyes@solliance.net)
www.solliance.net

Server Side

  • BreezeController vs OData vs client enriching

Query Calling Pattern

  • Client > executeQuery(query) > Entity Manager > GET Metadata from Controller (first time) > GET Query the controller > Return Query Results

SaveChanges Calling Pattern

  • Client > saveChanges > Entity Manager > POST Modified Entity ChangeSet > Controller > Return Server Persisted Entities

RPC, CRUD, REST, ODATA Services

  • Breeze routing is action-based (contains an entire model) > by default using a WebActivator.PreApplicationStartMethod(...)
  • OData query parameters are turned into an expression tree that is executed against the return IQueryable by the query filter
  • SaveChanges takes a JObject bundle with a batch of entities.

Extend EFContextProvider to add custom code

  • BeginSaveEntity, BeginSaveEntities (Derived or Delegated)
_ContextProvider.BeforeSaveEntitiesDelegate = BeforeSaveEntities;
private Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo> saveMap)
{
var validator = new ProductValidator();
foreach (var type in saveMap.Keys)
{
if (type == typeof(Product))
foreach (var productEntityInfo in saveMap[type])
{
validator.Validate((Product)productEntityInfo.Entity)
}
}
}

Working with OData Services

  • On client data.js is needed
  • Server needs to define Entity Data Model with same namespace as entity types namespace
  • Metadata returned from the server needs to include foreign key relation information
  • Need some changes to the way you setup Entity Data Model and return metadata from the server
public class ZzaODataService : DataService<ZzaEntities>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Products", EntitySetRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
}
}

public static void RegisterRoutes(RouteCollection routes)
{
...
routes.IgnoreRoute("{resource}.svc/{*pathInfo}");
...
}

  • edmx > properties > Namespace: ZzaODataWeb (same project space as service)

app = {};
breeze.config.initializeAdapterInstance({dataService:"OData"});
em = new breeze.EntityManager("ZzaODataService.svc");

  • GET /ZzaODataService.svc/$metadata (returns xml)
  • GET /ZzaODataService.svc/Products
  • POST /ZzaODataService.svc/$batch (multi-part mime message)

Breeze Query Basics

app.em = new breeze.EntityManager("breeze/Zza");
breeze.EntityQuery.from("Products").where("Description","contains","bacon");
app.em.executeQuery(query).then(...).fail(...);

var p = new breeze.Predicate("Description","contains","bacon");
... .where(p);

var gteMay1 = new breeze.Predicate("OrderDate", "greaterThanOrEqual", moment("2013-05-01");
var lteMay31 = new breeze.Predicate("OrderDate", breeze.FilterQueryOp.LessThanOrEqual, moment("2013-05-31");
...
var predicate = breeze.Predicate.and(gteMay1, lteMay31, gt100);

... orderBy("Name");
... orderBy("TotalPrice, Order.OrderDate");
... orderBy("OrderDate desc").skip(currentPage() * pageSize).take(pageSize);

... orderBy("OrderDate desc").skip(currentPage() * pageSize).take(pageSize).inlineCount();

... select("LastName, Phone, State");
... from("OrderItems").where("Order.Customer.LastName","equals", queryInput()).select("Order.OrderDate, Product.Name, Quantity");
-> use Product_Name, Order_OrderDate to reference the projected elements.

... query.expand("Orders,Orders.OrderDetails,Orders.OrderDetails.Product"); //eagerloading

Breeze Query Advanced

Pre-fetching Metadata is needed when getting by id or creating.
... EntityManager.fetchMetadata().fail(...);

... EntityManager.fetchEntityByKey("Products", key).then(...);


public object Lookups()
{
var products = _ContextProvider.Context.Products.ToList();
...
return { products, productOptions };
}
breeze.EntityQuery.from("Lookups");
... data.results[0].products
... data.results[0].productOptions

public IQueryable<OrderItem> OrderItemsWithCouponCode(string couponCode, string customerClass)
{
...
}
var query = breeze.EntityQuery.from("OrderItemsWithCouponCode").withParameters({ couponCode:"XYZ", customerClass:"Gold"});

Server-Driven Queries (group by, sum, ...)
public IQueryable<object> TopCustomers()
{
var query = (from o in _ContextProvider.Context.Orders
group o by o.CustomerId into g
select new { Customer = g.FirstOrDefault().Customer.LastName, Total = g.Sum(o => o.ItemsTotal) }).OrderByDescending(a => a.Total);
return query;
}
... from("TopCustomers").take(10);

... requeryProducts.push(product)
... fromEntities(requeryProducts); //or by id that replaces the cache, you can also put a sigle entity

breeze.EntityQuery.from("Products").where(...)
... em.executeQueryLocally(query); //synchronous
query.using(breeze.FetchStrategy.FromLocalCache); //async with promise

EntityAspect: contains metadata and state information about the entity

  • breeze.NamingConvention.camelCase.setAsDefault(); //type and collections are pascal case, properties or camelcase

EntityManager.createEntity: creates instance and add to cache
newCustomer = function() {
var cust - em.createEntity("Customer", { id: breeze.core.getUuid() });
return cust;
}

EntityType.createEntity: reference from meta, entity from meta, create, add to cache
newCustomer = function() {
var metadataStore = em.metadataStore;
var custType = metadataStore.getEntityType("Customer");
var cust = custType.createEntity({ id: breeze.core.getUuid() });
em.addEntity(cust);
return cust;
}

var pendingStatus = em.executeQueryLocally(breeze.EntityQuery.from("OrderStatuses").where("name", "equals", "Pending"))[0];
order.orderStatusId(pendingStatus.id());
return order;

addToOrder = function(product) {
if (!Order()) order(zzaDataService.createNewOrder(customer()));
var orderItem = order().entityAspect.entityManager.createEntity("OrderItem");
orderItem.order(order());
orderItem.product(product);
orderItem.productSizeId(1);
orderItems.push(orderItem);
}

editingCustomer().entityAspect.rejectChanges();
em.rejectChanges();

//after accepting changes you will not be able to persist them !
... entityAspect.acceptChanges(); //should only be used when mocking data

customer.entityAspect.setDeleted();
customers.remove(customer);

Named Saves
zzaDataService.saveCustomers().fail(...)
...
var customers = em.getChanges("Customer");
return em.saveChanges(customers);
...
var saveOptions = new breeze.SaveOptions({ resourceName:"SaveOrder" });
var orders = [order];
return em.saveChanges(orders, saveOptions);
...
[HttpPost]
public SaveResult SaveOrder(JObject saveBundle)
{
return _ContextProvider.SaveChanges(saveBundle);
}

Working with Entities on the client

Entity States:

  • Unchanged - after being loaded by a query or after successful saveChanges
  • Modified - previously unchanged entity has a property change
  • Added - entity has been created and added to the cache, but not saved to back end
  • Deleted - previously unchanged entity is marked for deletion
  • Detached

Newly created entity that has not been added to the cache
Added entity that gets marked for deletion
Deleted entity after saveChanges is complete
Entities that were in the cache when EntityManager.clear is called
EntityManager.detachEntity called
EntityAspect.entityState
createEntity, setDeleted, rejectChanges, acceptChanges
EntityAspect.setModified, EntityAspect.setUnchanged

Extending Entities: Modify the EntityType in the Breeze metadataStore
Saved when exported, but not persisted to the server.

addEntityExtensions = function () {
var store = em.metadataStore;
store.registerEntityTypeCtor("Customer", Customer)
}
var Customer = function() {
this.firstName = ko.observable(''); //solves race condition
this.lastName = ko.observable('');
this.fullName = ko.computed(function() {
return this.firstName() + " " + this.lastName();
}, this);
}
OR
Customer.prototype.getFullName = function() {
return this.firstName() + " " + this.lastName();
}

Handling Entity Property Changes

  • Breeze raises its own (observable agnostic) property change events
  • EntityAspect.propertyChanged.subscribe returns a subscription token
  • Avoid memory leaks by EntityAspect.propertyChanged.unsubscribe(token)
tokens = {};
var token = addingCustomer().entityAspect.propertyChanged.subscribe(function()arg {
logger.info("Customer:" + arg.entity.fullName() + "property " + arg.propertyName + "changed value" + arg.oldValue + "into" + arg.newValue);
})
tokens[addingCustomer().id] = token;
... unsubscribe(tokens[customers()[i].id]) ...

EntityManager.entityChanged.subscribe (eg. undo)
-> entityAction, entity, args

Exporting and importing cached entities
Using an entityChangedHandler to make sure changes are saved locally for when user would close browser before saving
var bundle = em.exportEntities(em.getChanges());
window.localStorage.setItem("magickey", bundle);
...
var bundle = window.localStorage.getItem("magickey");
if (bundle) em.importEntities(bundle);
...
clear local storage on save

Validation

  • Returns HTTP 403 Forbidden status code when validation errors
  • Collection of ValidationError objects per entity (propertyName, property, errorMessage, context, isServerError, key, validator)
  • Automatically adds type, required and length validation
  • Configurable - EntityManager.validationProperties
saveError = function (error) {
if (error.entityErrors) {
showValidationErrors(error.entityErrors);
}
else {
logger.error(error.message, "Error saving data");
}
}
showValidationErrors = function (errors) {
var errorMessage = "";
errors.map(function (e) {
if (errorMessage.length > 0) errorMessage += ", ";
errorMessage += e.errorMessage;
});
logger.error(errorMessage, "Validation Errors");
}

Data Annotations (System.ComponentModel.DataAnnotations)
[Required], [StringLength(50)], Range, RegularExpresssion, Compare
[DataType(DataType.Currency)], Date, Time, DateTime, PostalCode, ...
Phone, [EmailAddress], CreditCard, Url

function initValidation(em) {
var store = em.metadataStore;
var userType = store.getEntityType("User");
var phoneProp = userType.getProperty("phone");
phoneProp.validators.push(breeze.Validator.phone());
}

var userKeyValidator = breeze.Validator.makeRegExpValidator(
"userKeyVal",
/^[A-Z] ... regex ... $/,
"%displayName% '%value%' is not a valid GUID");
);

if (validateUser(editingUser()) { ... saveChanges ... }
validateUser = function(user) {
if (!user.entityAspect.validateEnitity()) {
var errors = user.entityAspect.getValidationErrors();
showValidationErrors(errors);
return false;
}
return true;
}


function isValidScoreRange(value, context) {
return value > context.minValue && value <= context.maxValue;
}
var scoreRangeValidator = new breeze.Validator("scoreRangeValidator", isValidScoreRange, { messageTemplate: '...' });
userType.getProperty("score").validators.push(scoreRangeValidator);
function rangeValidatorFactory(context) {
return new breeze.Validator("rangeValidator", isValidRange,
{
minValue: context.minValue,
maxValue: context.maxValue,
messageTemplate: '... %minValue% ... %maxValue% ...'
OR messageTemplate: breeze.core.formatString("'... %1 ... %2'", context.minValue, context.maxValue)
}
);
}
userType.getProperty("score").validators.push(rangeValidatorFactory({ minValue:1, maxValue:100 }));

//register to allow export and imports
breeze.Validator.register(userKeyValidator);
breeze.validator.registerFactory(rangeValidatorFactory, "rangeValidator");


app.em.validationErrorChanged.subscribe(function(args) {
if (args.added) ...
}


editSubscriptionToken = editingUser().entityAspect.validationErrorsChanged.subscribe(...);
... unsubscribe ...


Customer Server Validation

  • Inherit from ValidationAttribute
  • CustomValidatorAttribute
  • Custom business logic (EntityErrorsException from BreezeController BeginSaveEntity)
  • [CustomValidation(typeof(UserValidationRules), "ValidateEmail")]
public static class UserValidationRules
{
public static ValidationResult ValidateEmail(string value, ValidationContext context)
{
if (!value.EndsWith("...") return new ValidationResult("...");
return ValidationResult.Success;
}
}

private bool BeforeSaveEntity(EntityInfo entityInfo)
{
User user = entityInfo.Entity as User;
if (user != null)
{
if (!user.CreditCard.StartsWith("5"))
{
throw new EntityErrorsException(new List<EntityErrors>)
{
new EntityError
{
EntityTypeName = user.GetType().ToString(),
ErrorMessage = "We only accept Mastercard",
PropertyName = "CreditCard",
ErrorName = "CreditCardValidationError",
KeyValues = new object[] { user.Id }
}
}
}
}
return true;
}

WASABi Elastic Azure Scaling 

Categories: Azure Notes

Notes on Azure Elastic Scaling by Zoiner Tejada. This is again one of these PluralSight courses, where only the sample project is worth the membership to the site. Get it there. Check also: Channel 9 Autoscaling in Windows Azure 2013

Dodging the 503 server busy response

Scale for performance, capacity & availability
vs
Costs of over-allocating (Ideally paying for exactly what is needed)

Scale out/in: adding/removing number of instances

Scale up/down: increasing/decreasing the power of resources

Database can be scaled out by sharding with federations

Elastic Scale: The ability to adjust resources according to demand.

Scaling vs Throttling

Things needed to allow automating scaling

  • Build tooling to monitor cloud service's key performance
  • Use the Windows Azure Service Management API from your code
  • Collect diagnostics
  • Maximize clock hour use in scaling decisions
  • Send admins notification
  • Manage cool down periods between scaling actions

WASABi

WASABi diagram of components

Autoscaler

  • Metronome: collects kpi data
  • Scaler + Stabilizer: manage scale and notifications
  • Tracker: log outcome of actions

Using WASABi

  1. Add reference to WASABI library from your project 
  2. Nuget: Autoscaling Application BLock
  3. Instantiate Autoscaler in code : var autoscaler = EnterpriseLibraryContainer.Current.GetInstance<Autoscaler>(); autoscaler.Start();
  4. Configure App, Service Information Store and Rules Store
  5. Deploy and run

Rule Evaluation
Contstraint rules over Reactive rules
Rule with highest integer rank wins
Intelligent scaling action on tie breaking

ServiceInfo.xml
Scale and/or notifications
Stabilizer ScaleUpOnlyInFirstMinutesOfHour
Stabilizer ScaleDownOnlyInLastMintesOfHour

WASABi in Azure
Management Certificate
makecert -sky exchange -r -n "CN=<CertificateName>" -pe -a sha1 -len 2048 -ss My"<CertificateName>.cer"
via azure portal, settings, mgmt certs, upload
backup .pfx with password
export via mmc, certs snap-in, personal, export
put public and private key on machine running autoscaler

Add WASABi nuget
Add Enterprise Library config nuget

Update app.config (right-click)
point to Rules.xml
point to ServiceInfo.xml
add smtp info

Update ServiceInfo.xml
Make sure you save as utf-8 without signature!
Add xsd to schema
Update subscription
Update service
Update roles
Update stabilizer

Update Rules.xml
ConstraintRules eg. ScaleTargetHost min="2" max="6"
ReactiveRules eg. greaterOrEqual operand="averageCPU" than="30"
Operands eg. alias="averageCPU" performanceCOunterName="..."

Update diagnostics.wadcfg
eg. PerformaceCounters scheduledTransferPeriod="PT1M"

Pubish Web Role and Run Web Worker Autoscaler

Custom Operands
When performance counters, queue length or instance count aren't enough
For use by reactive rules only
eg. Queue msg depth, number of files in blob, business tickets, ...
Extend DataPointsParametersElement using IDataPointsCollector

Custom Actions
When adjusting instance count or changing settings isn't enough
eg. change role instance size, scale vm website db storage, send sms messages
Extend ReactiveRuleActionElement using instance of ReactiveRuleAction
Remember to put in your custom namespaces (xmlns="http://myfoo")

Azure Websites 

Categories: Azure Notes

Notes from Windows Azure Websites by Matt Milner

  • Application load balancer
  • Content + configuration in shared storage
  • http://<account>.azurewebsites.net

Publishing

  • FTP, Web Deploy, Continues integration
  • Use EnableCodeMigrations to create the db and seed some default data
  • Use a publishing profile (import on web publish)
  • One ftp location even though you have multiple instances.

Pricing Models

  • Free only up to 10 sites, multi-tenant, limited dns entries, outbound data limits, throttles on cpu and memory usage.
  • Shared is multi-tenant, per site/instance charges, custom domain names, unlimited outbound charged separately.
  • Reserved is vm-size with 1-3 instances, up to 100 sites.

Monitoring
Counters: CPU, Data in/out, Http Errors, Requests
Diagnostics: Error pages, Logging, IIS logs, Failed request

Team Foundation Service
Setup publishing: Authorize and create build definition
Build: Publish to azure on succesful build

Local Git Repository
Setup publishing: Create repository on azure websites
Push: Push to git repository initiates build on azure
Build: Deploy to azure on succesful build

Solution

  • Make sure your dlls are correctly referenced (use nuget)
  • Correct your Web.Release.config (use preview transformation)
  • .gitignore (packages/ bin/ obj/ *.suo *.csproj.user)

Azure

  • Setup Git Publishing
  • git remote add fooazurealias https://<account>/foo.git
  • git push fooazurealias master

Hosted Git Repository
Codeplex, GitHub, BitBucket
Setup publishing: Create repo on azure, authenticate hosted with oauth
Push: Push to hosted, will post notification to azure, azure will clone repo
Link your Azure website to a specific branch on github.com

Windows Azure PowerShell

get-module

get-command -module azure

$mgmtCert = get-item cert:\\currentuser\my\$mgmtCertThumbprint

Set-AzureSubscription -SubscriptionName KensCloud -SubscriptionId $subscriptionID -Certificate $mgmtCert

Select-AzureSubscription -SubscriptionName KensCloud

get-azurewebsite

get-azurelocation

New-AzureWebsite -Location "West US" -Name "fooNew"

$site = get-azurewebsite -Name fooNew

$site

$site.HttpLoggingEnabled = $true

$site.RequestTracingEnabled = $true

$site.NumberOfWorkers = 3

$site | Set-AzureWebsite

Node.js

npm install azure-cli

node azure account download

node azure account import c:\foo\foo.cer

del c:\foo\KensCloud-11-11-2011-credentials.publishsettings

node azure site create KensNode

node azure site browse KensNode
Page 1 of 5 1 2 3 4 5 > >>