by msimpson
11/6/2007 3:18:00 PM
I've been having issues with my old wireless router (a Linksys WRT54G v5) - once or twice a month it just locks up and stops passing traffic through. When that happens I have to either bounce the router or at least go into the admin interface, change a setting and have it refresh. This has been highly annoying and given that I run this web site on a server at home, disruptive. Through some web research plus trial and error over the space of a few months, I determined that it had something to do with the wireless connection itself; so for the past few weeks I've had wireless disabled. My house is wired for ethernet anyway.
But who wants to pay for something and not get it? I do occasionally want to work upstairs in the dining room, and my wife's PC is plugged in up there, so wireless (assuming it works) is the way to go. So I bought another router. This one's a Linksys WRT54GL, Linux-based, with excellent reviews. I installed it tonight and put a third-party firmware on it (DD-WRT). The new firmware has tons more options, and so far, the unit seems to be working like a champ. Problem solved! I hope.
by msimpson
11/6/2007 11:09:00 AM
I've been hesitant to start my recording project because I have a lot going on at work and because my home studio has some serious drawbacks. The room is an acoustical pigsty, and it's worsened by the fact that my laptop (which I've been trying to use to record) sounds like a Boeing 747.
However, I've virtualized and turned off the server I had running in there, and I'm making progress on work issues, so as soon as I can build a quieter PC I'm looking forward to doing some recording. This should happen by Christmas, at which point I plan to have one or more demo tracks available on this site. Then I'll be a REAL musician ;-)
by msimpson
11/6/2007 10:33:00 AM
Below are some code samples using the Slipjig framework.
Here's some code to create and save a simple entity tree:
Vendor v = new Vendor();
v.VendorName = "Oracle";
Product p = new Product();
p.Vendor = v;
p.ProductSKU = "ORDB10G";
p.ProductName = "Oracle 10g";
v.Products.Add(p);
p = new Product();
p.Vendor = v;
p.ProductSKU = "ORSVC10";
p.ProductName = "Oracle Services For Java 10";
v.Products.Add(p);
v.Persist();
Here's an example showing how to load all instances of a given entity, using a static entity method:
List<Customer> custs = Customer.LoadAll();
Two more examples showing ways to load entities using a template (query-by-example):
Product pt = new Product();
pt.ProductSKU = "VS2005PRO";
List<Product> list1 = Product.LoadByTemplate(pt);
Vendor vt = new Vendor();
vt.VendorName = "Microsoft";
TemplateLoader<Vendor> ldr = new TemplateLoader<Vendor>(vt);
List<Vendor> list2 = ldr.Load();
Loading one or many entities by key:
Order o = Order.LoadByKey("123");
List<Order> orders = Order.LoadByKey(new string[] { "123", "456" });
Slipjig can set up a data command to call any arbitrary stored procedure. It also provides a method to set all the parameter values in one shot. This is more of an ad-hoc convenience thing than anything else; in particular, SetParamValues() is not type-safe and wouldn't be part of everyday usage. Here's a sample calling a stored proc that takes an instance of every data type:
using (IDbSql db = (IDbSql)DbFactory.GetDB("Test")) {
IDbCommand cmd = db.GetStoredProcCommand("usp_test");
db.SetParamValues(cmd, 1, 1, 1, 1, "a", "a", "a", "a", "a", "a", "a", "2006-02-24", "2006-02-24", 0, new byte[] {}, new byte[] {}, new byte[] {}, new byte[] {}, 0m, 0m, 0, 0, 0, Guid.NewGuid(), 0);
int recs = db.ExecuteNonQuery(cmd);
}
by msimpson
11/6/2007 10:29:00 AM
For several years now I've disliked how ASP.NET provides a page lifecycle that is unrelated to the "business", or let's say, "functional" side of the application domain, and is pretty inflexible. The ASP.NET page lifecycle is strictly in the technical domain, with the possible exception of the Validate() method. This lifecycle is pretty low-level.
However, typical applications have a higher-level set of actions, many of which are performed by the user: things like "Save", "Save and Add New", "Authorize", "Create From Template", "Cancel", "Delete", "Select", etc. The natural thing to do is create an API within the application to support these activities. If you're lucky, you can make this a cross-cutting API that works generically for each feature on all the applicable pages.
The problem is that there's an impedance mismatch between the ASP.NET lifecycle API and the (for lack of a better word) "business domain" API. It can be hard to determine where in the ASP.NET model to put certain code. What's worse, it may need to be in a different place in one page than in another; for example, before loading some data in Page_Load(), you may need to know whether you will be handling some event from a control, or you may need to handle the event first.
I understand that in .NET 2.0 it's actually possible to override the code that provides the ASP.NET page lifecycle, but this seems like a drastic solution and one that leads to a hard-to-maintain application. I've also read about some efforts towards aspect-orientation that might provide some relief.
One solution I thought of is to have some sort of state machine that would allow specification of the lifecycle in a database or other structure, and then fire things off dynamically. This would be embedded in Page_Load() or some other standard place, and would give developers full control over how the page runs, with the benefit of being able to use a standard, business-oriented lifecycle API.
Food for thought :-)
by msimpson
11/6/2007 10:22:00 AM
For the past year or two I've been crystallizing some thoughts about frameworks based on my experiences developing and using ASInet 2, Philidor and Morphy (applications and frameworks I developed for my company). Although these frameworks are useful, they rely too heavily on ADO.NET DataSets and DataTables, expose too many low-level tasks to the developer, have a steep learning curve, and generate a lot of code which leads to long startup times and low productivity.
With these thoughts in mind, in my spare time (!) in the last year I've been working on a new framework, tentatively called "Slipjig", that attempts to address these concerns. Slipjig is based on .NET 2.0 and is much more dynamic than my previous efforts. Here are the major design ideas:
-
The entities contain their own data, rather than binding to DataRows. LINQ will enable us to query an entity tree as if it were a database.
-
Entities have direct references to other entities, providing for parent, child, peer, and many-to-many relationships. The framework can load and save an entire entity tree automatically.
-
The entities use attributes to specify object-relational mapping information, rather than code in the entity or in separate but related data access classes. This reduces the project footprint considerably and yields faster startup times.
-
A property on the entity controls how the entity will get persisted. Though normally this property is set automatically based on how the entity is used, the developer has complete control over how each entity is persisted.
-
The data access layer eschews DataSets completely. Instead, it uses dynamically-generated mapping classes to move data between entities and ADO.NET DataCommands/DataReaders. The mapping classes are generated only on first data access for each entity, yielding even faster startup times. So if you are unit testing a code change in only one module out of 100, the framework only generates and loads the necessary code.
-
The data access layer uses the concept of a "loader" - a class that pulls data from a data source and populates a number of entities from it. There are different loaders for different scenarios, and developers can write their own loaders. The data access layer provides implicit transaction support with no need for the developer to do anything.
-
The data access layer automatically batches commands for better performance. It also observes a consistent save order for the tables, to prevent deadlocks in the database. The framework uses a table and stored procedure to assign its own keys, rather than use identity columns. This provides a number of advantages, chief among them the ability to assign keys in advance of hitting the database. The framework grabs a batch of keys from the database when it needs to, and doles them out to entities as needed, rather than hit the database for each key. This avoids contention on the key table. Keys are assigned to the entities automatically - the developer does not need to worry about this.
The current status is that I'm working on the loaders, to get them loading the entire entity tree. I'm making changes as necessary to support that. The "save" side of things is working, though I have a few to-dos there too: getting the table save order and command batching fully implemented, and providing more hooks for the developer to control exactly which parts of an entity tree get persisted.
If you're a developer and want to take a look at the framework, give me a shout and I'll get you SVN access :-)