Skip to content

Commit 18f82d0

Browse files
author
Garry Shutler
committed
Changed markup of code blocks in the README so that it should have syntax highlighting.
1 parent 2f48d1c commit 18f82d0

File tree

1 file changed

+135
-97
lines changed

1 file changed

+135
-97
lines changed

README.markdown

Lines changed: 135 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -21,57 +21,74 @@ Massive is a "wrapper" for your DB tables and uses System.Dynamic extensively. I
2121
Code Please
2222
-----------
2323
Let's say we have a table named "Products". You create a class like this:
24-
25-
public class Products:DynamicModel {
26-
//you don't have to specify the connection - Massive will use the first one it finds in your config
27-
public Products():base("northwind", "products","productid") {}
2824

29-
}
25+
```csharp
26+
public class Products:DynamicModel {
27+
//you don't have to specify the connection - Massive will use the first one it finds in your config
28+
public Products():base("northwind", "products","productid") {}
29+
}
30+
```
3031

3132
You could also just instantiate it inline, as needed:
3233

33-
var tbl = new DynamicModel("northwind", tableName:"Products", primaryKeyField:"ProductID");
34+
```csharp
35+
var tbl = new DynamicModel("northwind", tableName:"Products", primaryKeyField:"ProductID");
36+
```
3437

3538
Or ignore the object hierarchy altogether:
3639

37-
Massive.DB.Current.Query(...);
40+
```csharp
41+
Massive.DB.Current.Query(...);
42+
```
3843

3944
Now you can query thus:
4045

41-
var table = new Products();
42-
//grab all the products
43-
var products = table.All();
44-
//just grab from category 4. This uses named parameters
45-
var productsFour = table.All(columns: "ProductName as Name", where: "WHERE categoryID=@0",args: 4);
46+
```csharp
47+
var table = new Products();
48+
//grab all the products
49+
var products = table.All();
50+
//just grab from category 4. This uses named parameters
51+
var productsFour = table.All(columns: "ProductName as Name", where: "WHERE categoryID=@0",args: 4);
52+
```
4653

4754
That works, but Massive is "dynamic" - which means that it can figure a lot of things out on the fly. That query above can be rewritten like this:
4855

49-
dynamic table = new Products(); //"dynamic" is important here - don't use "var"!
50-
var productsFour = table.Find(CategoryID:4,columns:"ProductName");
56+
```csharp
57+
dynamic table = new Products(); //"dynamic" is important here - don't use "var"!
58+
var productsFour = table.Find(CategoryID:4,columns:"ProductName");
59+
```
5160

5261
The "Find" method doesn't exist, but since Massive is dynamic it will try to infer what you mean by using DynamicObject's TryInvokeMember. See the source for more details. There's more on the dynamic query stuff down below.
5362

5463
You can also run ad-hoc queries as needed:
5564

56-
var result = tbl.Query("SELECT * FROM Categories");
65+
```csharp
66+
var result = tbl.Query("SELECT * FROM Categories");
67+
```
5768

5869
This will pull categories and enumerate the results - streaming them as opposed to bulk-fetching them (thanks to Jeroen Haegebaert for the code). If you need to run a Fetch - you can:
5970

60-
var result = tbl.Fetch("SELECT * FROM Categories");
71+
```csharp
72+
var result = tbl.Fetch("SELECT * FROM Categories");
73+
```
6174

62-
If you want to have a Paged result set - you can:
75+
If you want to have a paged result set - you can:
6376

64-
var result = tbl.Paged(where: "UnitPrice > 20", currentPage:2, pageSize: 20);
77+
```csharp
78+
var result = tbl.Paged(where: "UnitPrice > 20", currentPage:2, pageSize: 20);
79+
```
6580

6681
In this example, ALL of the arguments are optional and default to reasonable values. CurrentPage defaults to 1, pageSize defaults to 20, where defaults to nothing.
6782

68-
What you get back is IEnumerable < ExpandoObject > - meaning that it's malleable and exciting. It will take the shape of whatever you return in your query, and it will have properties and so on. You can assign events to it, you can create delegates on the fly. You can give it chocolate, and it will kiss you.
83+
What you get back is `IEnumerable<ExpandoObject>` - meaning that it's malleable and exciting. It will take the shape of whatever you return in your query, and it will have properties and so on. You can assign events to it, you can create delegates on the fly. You can give it chocolate, and it will kiss you.
6984

7085
That's pretty much it. One thing I really like is the groovy DSL that Massive uses - it looks just like SQL. If you want, you can use this DSL to query the database:
7186

72-
var table = new Products();
73-
var productsThatILike = table.Query("SELECT ProductName, CategoryName FROM Products INNER JOIN Categories ON Categories.CategoryID = Products.CategoryID WHERE CategoryID = @0",5);
74-
//get down!
87+
```csharp
88+
var table = new Products();
89+
var productsThatILike = table.Query("SELECT ProductName, CategoryName FROM Products INNER JOIN Categories ON Categories.CategoryID = Products.CategoryID WHERE CategoryID = @0",5);
90+
//get down!
91+
```
7592

7693
Some of you might look at that and think it looks suspiciously like inline SQL. It *does* look sort of like it doesn't it! But I think it reads a bit better than Linq to SQL - it's a bit closer to the mark if you will.
7794

@@ -81,76 +98,88 @@ Massive is built on top of dynamics - so if you send an object to a table, it wi
8198

8299
You can send just about anything into the MassiveTransmoQueryfier and it will magically get turned into SQL:
83100

84-
var table = new Products();
85-
var poopy = new {ProductName = "Chicken Fingers"};
86-
//update Product with ProductID = 12 to have a ProductName of "Chicken Fingers"
87-
table.Update(poopy, 12);
101+
```csharp
102+
var table = new Products();
103+
var poopy = new {ProductName = "Chicken Fingers"};
104+
//update Product with ProductID = 12 to have a ProductName of "Chicken Fingers"
105+
table.Update(poopy, 12);
106+
```
88107

89108
This also works if you have a form on your web page with the name "ProductName" - then you submit it:
90109

91-
var table = new Products();
92-
//update Product with ProductID = 12 to have a ProductName of whatever was submitted via the form
93-
table.Update(poopy, Request.Form);
110+
```csharp
111+
var table = new Products();
112+
//update Product with ProductID = 12 to have a ProductName of whatever was submitted via the form
113+
table.Update(poopy, Request.Form);
114+
```
94115

95116
Insert works the same way:
96117

97-
//pretend we have a class like Products but it's called Categories
98-
var table = new Categories();
99-
//do it up - the new ID will be returned from the query
100-
var newID = table.Insert(new {CategoryName = "Buck Fify Stuff", Description = "Things I like"});
118+
```csharp
119+
//pretend we have a class like Products but it's called Categories
120+
var table = new Categories();
121+
//do it up - the new ID will be returned from the query
122+
var newID = table.Insert(new {CategoryName = "Buck Fify Stuff", Description = "Things I like"});
123+
```
101124

102125
Yippee Skippy! Now we get to the fun part - and one of the reasons I had to spend 150 more lines of code on something you probably won't care about. What happens when we send a whole bunch of goodies to the database at once!
103126

104-
var table = new Products();
105-
//OH NO YOU DIDN't just pass in an integer inline without a parameter!
106-
//I think I might have... yes
107-
var drinks = table.All("WHERE CategoryID = 8");
108-
//what we get back here is an IEnumerable < ExpandoObject > - we can go to town
109-
foreach(var item in drinks){
110-
//turn them into Haack Snacks
111-
item.CategoryID = 12;
112-
}
113-
//Let's update these in bulk, in a transaction shall we?
114-
table.Save(drinks);
127+
```csharp
128+
var table = new Products();
129+
//OH NO YOU DIDN't just pass in an integer inline without a parameter!
130+
//I think I might have... yes
131+
var drinks = table.All("WHERE CategoryID = 8");
132+
//what we get back here is an IEnumerable < ExpandoObject > - we can go to town
133+
foreach(var item in drinks){
134+
//turn them into Haack Snacks
135+
item.CategoryID = 12;
136+
}
137+
//Let's update these in bulk, in a transaction shall we?
138+
table.Save(drinks);
139+
```
115140

116141
Named Argument Query Syntax
117142
-------------------
118143
I recently added the ability to run more friendly queries using Named Arguments and C#4's Method-on-the-fly syntax. Originally this was trying to be like ActiveRecord, but I figured "C# is NOT Ruby, and Named Arguments can be a lot more clear". In addition, Mark Rendle's Simple.Data is already doing this so ... why duplicate things?
119144

120145
If your needs are more complicated - I would suggest just passing in your own SQL with Query().
121146

122-
//important - must be dynamic
123-
dynamic table = new Products();
147+
```csharp
148+
//important - must be dynamic
149+
dynamic table = new Products();
124150

125-
var drinks = table.FindBy(CategoryID:8);
126-
//what we get back here is an IEnumerable < ExpandoObject > - we can go to town
127-
foreach(var item in drinks){
128-
Console.WriteLine(item.ProductName);
129-
}
130-
//returns the first item in the DB for category 8
131-
var first = table.First(CategoryID:8);
132-
133-
//you dig it - the last as sorted by PK
134-
var last = table.Last(CategoryID:8);
135-
136-
//you can order by whatever you like
137-
var firstButReallyLast = table.First(CategoryID:8,OrderBy:"PK DESC");
138-
139-
//only want one column?
140-
var price = table.First(CategoryID:8,Columns:"UnitPrice").UnitPrice;
141-
142-
//Multiple Criteria?
143-
var items = table.Find(CategoryID:5, UnitPrice:100, OrderBy:"UnitPrice DESC");
151+
var drinks = table.FindBy(CategoryID:8);
152+
//what we get back here is an IEnumerable < ExpandoObject > - we can go to town
153+
foreach(var item in drinks){
154+
Console.WriteLine(item.ProductName);
155+
}
156+
//returns the first item in the DB for category 8
157+
var first = table.First(CategoryID:8);
158+
159+
//you dig it - the last as sorted by PK
160+
var last = table.Last(CategoryID:8);
161+
162+
//you can order by whatever you like
163+
var firstButReallyLast = table.First(CategoryID:8,OrderBy:"PK DESC");
164+
165+
//only want one column?
166+
var price = table.First(CategoryID:8,Columns:"UnitPrice").UnitPrice;
167+
168+
//Multiple Criteria?
169+
var items = table.Find(CategoryID:5, UnitPrice:100, OrderBy:"UnitPrice DESC");
170+
```
144171

145172
Aggregates with Named Arguments
146173
-------------------------------
147174
You can do the same thing as above for aggregates:
148175

149-
var sum = table.Sum(columns:Price, CategoryID:5);
150-
var avg = table.Avg(columns:Price, CategoryID:3);
151-
var min = table.Min(columns:ID);
152-
var max = table.Max(columns:CreatedOn);
153-
var count = table.Count();
176+
```csharp
177+
var sum = table.Sum(columns:Price, CategoryID:5);
178+
var avg = table.Avg(columns:Price, CategoryID:3);
179+
var min = table.Min(columns:ID);
180+
var max = table.Max(columns:CreatedOn);
181+
var count = table.Count();
182+
```
154183

155184
Metadata
156185
--------
@@ -161,46 +190,55 @@ In addition, if you want to generate an empty instance of a column - you can now
161190
Factory Constructor
162191
-------------------
163192
One thing that can be useful is to use Massive to just run a quick query. You can do that now by using "Open()" which is a static builder on DynamicModel:
164-
var db = Massive.DynamicModel.Open("myConnectionStringName");
193+
194+
```csharp
195+
var db = Massive.DynamicModel.Open("myConnectionStringName");
196+
```
165197

166198
You can execute whatever you like at that point.
167199

168200
Validations
169201
-----------
170202
One thing that's always needed when working with data is the ability to stop execution if something isn't right. Massive now has Validations, which are built with the Rails approach in mind:
171203

172-
public class Productions:DynamicModel {
173-
public Productions():base("MyConnectionString","Productions","ID") {}
174-
public override void Validate(dynamic item) {
175-
ValidatesPresenceOf("Title");
176-
ValidatesNumericalityOf(item.Price);
177-
ValidateIsCurrency(item.Price);
178-
if (item.Price <= 0)
179-
Errors.Add("Price can't be negative");
180-
}
204+
```csharp
205+
public class Productions:DynamicModel {
206+
public Productions():base("MyConnectionString","Productions","ID") {}
207+
public override void Validate(dynamic item) {
208+
ValidatesPresenceOf("Title");
209+
ValidatesNumericalityOf(item.Price);
210+
ValidateIsCurrency(item.Price);
211+
if (item.Price <= 0)
212+
Errors.Add("Price can't be negative");
181213
}
214+
}
215+
```
182216

183-
The idea here is that Validate() is called prior to Insert/Update. If it fails, an Error collection is populated and an InvalidOperationException is thrown. That simple. With each of the validations above, a message can be passed in.
217+
The idea here is that `Validate()` is called prior to Insert/Update. If it fails, an Error collection is populated and an InvalidOperationException is thrown. That simple. With each of the validations above, a message can be passed in.
184218

185219
CallBacks
186220
---------
187-
Need something to happen After Update/Insert/Delete? Need to halt BeforeSave? Massive has callbacks to let you do just that:
188-
189-
public class Customers:DynamicModel {
190-
public Customers():base("MyConnectionString","Customers","ID") {}
191-
192-
//Add the person to Highrise CRM when they're added to the system...
193-
public override void Inserted(dynamic item) {
194-
//send them to Highrise
195-
var svc = new HighRiseApi();
196-
svc.AddPerson(...);
197-
}
221+
Need something to happen after Update/Insert/Delete? Need to halt before save? Massive has callbacks to let you do just that:
222+
223+
```csharp
224+
public class Customers:DynamicModel {
225+
public Customers():base("MyConnectionString","Customers","ID") {}
226+
227+
//Add the person to Highrise CRM when they're added to the system...
228+
public override void Inserted(dynamic item) {
229+
//send them to Highrise
230+
var svc = new HighRiseApi();
231+
svc.AddPerson(...);
198232
}
233+
}
234+
```
235+
199236
The callbacks you can use are:
200-
*Inserted
201-
*Updated
202-
*Deleted
203-
*BeforeDelete
204-
*BeforeSave
237+
238+
* Inserted
239+
* Updated
240+
* Deleted
241+
* BeforeDelete
242+
* BeforeSave
205243

206244

0 commit comments

Comments
 (0)