Connecting to CRM Online

When working with the Dynamics CRM 2011 SDK and desktop utilities, it can be sometimes be frustrating to setup a connection within Outlook.

I posted this video to help those of you who aren’t certain why typing in your default https://yourorganization.crm.dynamics.com URL and username/password into your CRM-wizard is failing. This is one possible solution to a particular problem. The problem I was having is that despite everything being setup properly, I wasn’t able to get the wizard to find and recognize my organization.

Cheers.

Video

Posted in Uncategorized | Comments Off

Debugging Django Views with Aptana

Aptana is a free Eclipse-based IDE that is particularly useful for Python/Django programming and troubleshooting. However, while working on troubleshooting the Django content we were teaching in class, we ran into the frustrating scenario of not being able to debug our views/models and other Python modules.

This video shows you how to do it. It also shows how to take a Django project created with django-admin.py and set it up from scratch inside of Aptana so that you can debug it properly.
(You can check out the steps to setting up Django under IIS7 in my previous post, here : http://codesmartinc.com/2013/04/12/running-django-in-iis7iis8)

Video: http://youtu.be/IA4stgSjgjs

Posted in Django / Python, Gotchas, Training | Comments Off

Making a simple HTML doc (for beginners)

I met a smart young guy at the Tacoma Community College the other day who asked me about making web-pages.

I gave him a quick run-down of how it works, but he wasn’t sure he understood. This post should help him out.
Here’s a link to a public you-tube video I made for you.
http://www.youtube.com/watch?v=B0fMorp8_Ts&feature=youtu.be

Oh, and here’s another link to a youTube video explaining how to style your text on the webpage and add a title to it.
http://youtu.be/BAKndLgLI3w

This video explains how to create a Hyper-Link between 2 different HTML documents. 2 different HTML documents may actually constitute a “web-site”! So, all we need next are images to make the page look more interesting, and a place to host it all. (HyperLink video below…)
http://youtu.be/i0fB4bX0GMQ

Here’s how you can create a simple graphic in Microsoft Paint, save it as a JPG file, and display it in your web-page. This video also explains how to create a 2-column page and vertically align the text to the top of the column.
http://youtu.be/rZhVqj2CQ3Q

Here’s how to setup your own “free” HTML web server on a Windows XP machine.
http://youtu.be/7HcZfSc8Npk

Here’s how to setup your own “free” HTML web server on a Windows Vista/7/8 machine.
http://youtu.be/1WP5IpyeKRA

** Note ** if you need any more help, just email me.

Thanks,

Chad W. Stoker

Posted in Training, Uncategorized | Comments Off

Running Django in IIS7/IIS8

So I’ve been working hard on Python and Django training materials lately. There’s a client that was in desperate need of somebody to provide this type of training, and I was fortunate enough to have an experienced Python/Ruby programmer on staff that fit the bill. He and I worked together to come up with plenty of examples and concepts to cover for a 5-day compressed course on Beginning Python and Django!

The most exciting part of the course was the final 2 days, where the students began to apply some of their newly acquired Python skills toward Django manage.py, settings.py, urls.py, and other files. During this course, I took it upon myself to think through the best way for a primarily Microsoft-centric server shop to be able to leverage the full capabilities of Python/Django in a way that didn’t feel limiting, wasn’t overly batch-script based, and didn’t have too many complex steps.

I found many articles on hosting Django within IIS… that were very difficult to follow. I eventually came across this article… which I spent quite a bit of time deciphering and understanding. The “batch script” nature of the article is what confused me the most. However, I distilled it down a bit into some IIS user-interface driven steps that my students had an easier time following along with. These are those steps on a Windows 7 machine, and should be nearly identical for Windows Server 2008 and above: (**note** assumes you’ve already installed Python version 2.7 and Django 1.4+ in C:\Python27 )

1. Make sure CGI is checked on box.

  • A. Control Panel
  • B. Programs and Features
  • C. Turn Windows features on or off
  • D. IIS
  • E. World Wide Web Services
  • F. CGI (Check)
  • G. Click OK

2. Go to IIS Manager
3. Select the web server
4. Double-Click Web Platform Installer a.k.a. WPI (you may not have it, so skip to step 7 if that’s the case)
5. If it asks to update, do so
6. If update fails, you need to download to install
7. http://www.microsoft.com/web/downloads/platform.aspx
8. When you can launch WPI, search for FastCGI
9. Select and install WFastCGI
10. If install fails, add a key under HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node
This key’s path is Python\PythonCore\2.7\InstallPath
It’s value is C:\Python27\
11. Confirm that wfastcgi.py is in C:\Python27\Scripts\

  • Copy the wfastcgi.py file from C:\Python27\Scripts\ to your Django root site folder possibly at – C:\inetpub\wwwroot\[project site]

12. Go to web server, and ensure that IIS has icons for both CGI and FastCGI
This is at the root server level
13. Move your django project to wwwroot (assumes you knew how to create a Django project with django-admin.py startproject
)
14. Create a site in IIS. Give it some name. Point it to the path of your project. Give it a

port that won’t have conflicts, such as 8003
15. Double click Handler Mappings
16. Upper right-hand side, click Add Module Mapping
17.

  • Request path of *,
  • Module, select FastCgiModule,
  • Executable: “C:\Python27\python.exe|C:\inetpub\wwwroot\[project site]\wfastcgi.py”,
  • Name: “Django Handler”

18. Click Request Restrictions
19. On Mapping tab insure that Invoke handler only if request is mapped to, is NOT checked.
20. Click OK and Click OK
21. You will be asked if you want to add an entry to the FastCGI collection in IIS. Answer YES
22. Select the root server.
23. Double-Click FastCGI settings
24. You should have the Full Path to your Python.exe with an argument to your wfastcgi.py
25. Double-click it.
26. Click on Collection in Environment Variables property box and click the … button
27. Add 3 Environment variables:

  • DJANGO_SETTINGS_MODULE: [project name].settings,
  • PYTHONPATH:C:\inetpub\wwwroot\[project name] ,
  • WSGI_HANDLER: django.core.handlers.wsgi.WSGIHandler()

28. Click OK. then Click OK
29. navigate to http://localhost:8003

*** YOU’VE MADE IT TO THE END ***

Unfortunately, there’s more. There are some challenges getting Django to cough up “static files” which come in the form of *.css, *.jpg, *.js, and many… many… many more. As a result, you may need to create an “Application” within your newly created “Website” (used to be known as “Virtual Directory”). The trick here, is that once your Application is created… you need to navigate to the “Handler Mappings” module for that Application and “Remove” the Python-specific Http Handler that was created automatically. This will not affect the parent Web-Sites Handler-Mapping settings.

Here’s the complete video! (Quality is pretty bad… if you really want this video, let me know. I will give you a better quality link to it.)
http://youtu.be/kXbfHtAvubc

Happy configuration! Feel free to contact us if you’ve got questions!

Posted in Django / Python, Training | Tagged , , , , | 1 Comment

Semantic Data-Modeling Guidelines

For those of you that have heard me talk about “meta-data” modeling, or the concept of modeling data to support certain dynamic data-capture needs… this is for you. This white-paper, originally published by Microsoft, describes in a very methodical way, how a good data-modeler will potentially approach normal and static data-capture needs as opposed to dynamic data-capture scenarios.

It lays out the steps necessary to consider one design over the other, and several other common data-modeling best-practices. Check it out! This is a “must-read” for almost everyone at CodeSmart Inc. :-)

Cheers,

semantic db modeling by Microsoft

Posted in SQL, Technology Philosophy, Training | Tagged , , | Comments Off

SSRS for ASP.NET MVC3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
        private FileContentResult DownloadPdfReport(string reportPath, 
                                                    string fileName, 
                                                    IEnumerable reportDataSources)
        {
            var localReport = new LocalReport { ReportPath = reportPath };
            var permissionSet = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.Unrestricted);
            localReport.SetBasePermissionsForSandboxAppDomain(permissionSet);
            foreach (var dataSource in reportDataSources)
                localReport.DataSources.Add(dataSource);
 
            string reportType = "PDF";
            string mimeType;
            string encoding;
            string fileNameExtension;
 
            //The DeviceInfo settings should be changed based on the reportType
            //http://msdn2.microsoft.com/en-us/library/ms155397.aspx
            var deviceInfo =
                "" +
                "  PDF" +
                "  8.5in" +
                "  11in" +
                "  0.5in" +
                "  0.5in" +
                "  0.5in" +
                "  0.5in" +
                "";
 
            Warning[] warnings;
            string[] streams;
            byte[] renderedBytes
                = localReport.Render(reportType,
                                     deviceInfo,
                                     out mimeType,
                                     out encoding,
                                     out fileNameExtension,
                                     out streams,
                                     out warnings);
            Response.AddHeader("content-disposition", "attachment; filename=" + fileName + "." + fileNameExtension);
            return File(renderedBytes, mimeType);
        }
Posted in Uncategorized | Tagged , , | Comments Off

Mono For Android: Getting Started

Getting started with any new technology that you are not familiar with can be a little daunting so I wanted to write a little tutorial to help people get a head start and to pass on the things that I have learned through trial and error.

A Little Background on Mono

The Mono Project was started by Miguel de Icaza as an open source project on July 19, 2001 while working at Novell. The intent was to support the .NET Framework on Linux systems to help increase developer productivity. After Icaza was laid off when Novell was acquired by Attachmate in April 2011, he started the company Xamarin. This company was given a perpetual license and stewardship of the Mono, MonoTouch, and Mono for Android projects.

Setting Up Your Environment

You can go to the Xamarin installation documentation for detailed information on how to set up your development environment. The process is fairly straightforward and really just requires that you download the installer which will install all the required components for you.

After you have run the installer you will have the Trial Version which will allow you to develop Mono for Android applications and deploy them to the emulator for testing. In order to deploy the application to a device you must buy a license and activate it.

Creating Your First Mono For Android Application

The first step will be to open Visual Studio and create a new Android Application project.

Lets go ahead and name this project “HelloMonoDroid” and click OK.

Now we have a basic project that we we can begin to work with. Let’s start out by examining the structure of the Project

  • Properties Folder : Contains the AssemblyInfo.cs file where information about assembly and its permissions on the phone are located.
  • Reference Folder: Lists dlls that the application needs for functionality.
  • Assets Folder: Contains assets that the application needs; Text Files, Fonts, etc…
  • Resources Folder: Contains sub folders and files for resources as well as an autogenerated file to access these resources.
    • Drawable Folder: Contains image files used in the application.
    • Layout Folder: Contains .axml files that are used as designers for the different Views in the application,
    • Values Folder: Contains the Strings.xml file which is used for localization of the strings used in the application.
  • Activity Files: The logic for each screen of the Android application

The two files that we need to work with for the HelloMonoDroid application are the Main.axml and the Activity1.cs file.

The Main.axml file is the default designer file that the application will use to render a View when a new Android Application is created. This file can be renamed to whatever you would like and additional view can be created to work with this or replace it. A view can be a single control on the screen, the entire screen, a dialog, a menu, a list, etc… Because of this, for every View that we want to see, we need to create a new .axml file that corresponds to that View. For now we will just be creating a single View that will correspond to a single screen.

The Activity1.cs file is the generic name that is given the default Activity when an Android Application project template is used. The Activity acts as the controller for the application. An Activity can be thought of as the logic for the screen that is being displayed. The Activity uses the .axml file to render the controls that will be displayed on the screen and it is here that you can programatically interact with the controls and add the functionality that make the application go.

So lets get started.

Running The Default Application

Application Description

The Application that we will be making is a simple adding application that allows the user to enter a number in a text box, click an add button, and display the sum. We will also have a reset button to set the summed value back to zero.

Setting Up a Clean Project

First we will clean out our project to remove the default application content. I want to demonstrate to you guys how to create an application from scratch without the default files for the View and the Activity so we will go ahead and delete the Main.axml and the Activity1.cs files first.

Now that we have a clean project to start from we want to begin by creating a new View Layout (.axml file).

  • Right click on the Layouts folder and select a Add New Item.

  • From the Add New Item Dialog, select Android Layout and name it StartScreen.axml.

Depending on the version of Mono for Android that you have downloaded, you will get either a graphical designer or a xml file. I prefer to use the xml file for my design, and it gives you a clearer understanding of how to create a view, so that is how I will proceed.

If you have the graphical designer showing in your main window, you need to…

  • right click on the StartScreen.axml file in the solution explorer
  • and select ‘open with’ from the context menu. Then select Automatic Editor Selector (XML) from the dialog and click OK.

You will see the markup for the view in the main window.

*In a future blog I will do an in depth look at the View and take a look at most of the controls that you can work with, but for now we will keep it simple and confined to this demo.

Building The Screen

Like we talked about a little earlier, the Screen is represented by the axml file that is loaded by the Activity. We need to add the controls that we want on our screen to display. For this demo, that is a EditText for to allow the user to enter a number, a TextView to display the sum total, and a Button to add the number in the EditText to the sum.

(I will complete this post in the near future… in the meantime, here are the code sample from IPMA 2012 forum.)


Mono Development (w/ Android) powerpoint slide-deck

Mono Source-Code examples

Posted in Mobile Development, Training | Tagged , , | Comments Off

IPMA 2012 Forum

CodeSmart Inc supported the IPMA forum for our 4th year in a row. We are a little bit delayed in pulling together the samples from the MONO for Android presentation. We expect to have the content posted later this evening. This afternoon, I expect to have the content for the Responsive/Adaptive Design presentation posted.

Thanks to all who attended!

(Here are the updated links to the IPMA content!)

Chad Stoker – Adaptive and Responsive Design (source files)

Chad Stoker – Adaptive/Responsive Design (slide show)

Bryan Paslay – MonoDroid slides (IPMA 2012)

Bryan Paslay – MonoDroid source code!(IPMA 2012)

Chad Stoker – ASP.NET MVC3 power-point slides

Chad Stoker – ASP.NET MVC3 source-code

Ben Feely – WebDeploy, Knockout.js, and slides

Posted in Uncategorized | Tagged , , | Comments Off

Responsive and Adaptive Web Design

When software engineers first jump into understanding how to adjust their development techniques for mobile devices, they are bombarded with new tools, design considerations, new terminology, and more. So I will state right up-front, where this article is headed. If you are a .NET developer, more specifically, an ASP.NET developer responsible for web-application or web-site creation, then this article is for you.

This article is not about how to setup an Eclipse Android-enabled IDE or how Views in the Android SDK can best be written to support tablets versus cell-phones. It’s also not about the XCode environment and the nuances of writing Objective-C programming for iPads, iPods, iPhones, and the like. This article is about using your existing skills in ASP.NET for targeting these platforms successfully.

To get started, I feel I should explain the difference between Adaptive Design programming and Responsive Design programming.

Responsive Design -

is the easiest to explain. It simply means that you design your web-sites or applications to adapt to the capabilities of the user’s browser settings. So if a user is working with a cell-phone and a rediculously small screen resolution, then your web-site/application should render itself accordingly to make navigating the content easy and intuitive. If the user is on a desktop, then they should be able to view more than just a single tiny column of content at once.

Adaptive Design -

is the most ambiguous term ever, and essentially refers to how web-developers or web-masters may go about re-using techniques or designs from previous projects, on a new project. Sometimes, I have heard this called “Progressive Enhancement”. The idea is to avoid building all of your images, HTML markup, and CSS from scratch each time you start a new venture.

Examples and Discussion -

To beging with, let’s consider a couple of images from an actual website…

The image above shows a normal website shown at full-screen on a desktop browser with 1280 x 900 pixel resolution. Now let’s consider what the same website might look like if rendered on a tablet instead.

And finally… what would this website likely look like on a mobile-phone with something like 465 x 800 pixel resolution?

So… these images give us a starting point to understand more about what Responsive design and Progressive Enhancement (a.k.a. Adaptive Design) is all about. Obviously, there are a couple of take-aways about each of these 3 screen shots… but let me see if I can summarize a couple of Frequently Asked Questions (FAQ’s) here.

1) Are those 3 separate websites? If not, how is the web developer able to achieve such dramatically different visual appearances from the same markup?

2) How does HTML 5 fit into all of that?

3) How would this type of thing affect my project’s budget… if it is determined to be a priority?

4) What technologies do I need to know about?

Answers to the Questions -

1) These images are not taken from 3 separate websites. They are all, in fact, the same website… and I simply resized my browser in order to capture the behavior of each one at different resolutions. The secret to the behavior is called “MEDIA QUERIES”.

Media Queries are the single most important aspect of “Responsive Design” because they allow a web programmer to query the capabilities and current state of the browser and apply styling accordingly. In the past, HTML4 and CSS2 supported media types at a basic level. A common technique was to apply a different set of styles for a PRINT media versus the SCREEN media. For instance, here is some HTML4 markup that does just that…

<link rel="stylesheet" type="text/css" media="screen" href="sans-serif.css">
<link rel="stylesheet" type="text/css" media="print" href="serif.css">

The idea of the “media” attribute in the LINK tags above, is that browsers will interpret this markup based on the output device. So the browser, if it supports the standard, will render “serif.css” to a ‘print’ output device, but will instead render “sans-serif.css” to a screen output device. (Like the one you’re looking at now!) The details concerning syntax and history of “media queries” can be found here: http://www.w3.org/TR/css3-mediaqueries/

There is one little “gotcha” involved with this approach however. The designer/developer will end up making redundant style sheets for some of the same elements. That being said, how much redundancy occurs depends on the individual needs of your project. Most designs require only a small amount of duplicated styles. Like all things on the web, there are differences that must be taken into account on various browsers. So keep that in mind.

2) The HTML4 specification committee, luckily, was able to foresee the need for a forward-compatible syntax that would support media types that were unknown at the time. So, using the attribute below, is perfectly valid even though 3d glasses are not currently a media type that exists on any computing devices  that I’m aware of.

media="screen, 3d-glasses, print and resolution > 90dpi"

So, in this way HTML5 isn’t all that important. However, when we’re designing websites today… we need to think about targeting the HTML5 syntax where possible, and that means we need to think ways to make it backward compatible with the HTML4 browsers available today. (As opposed to continuing to produce HTML4 markup with no thought of HTML5 compatibility.) In order to do this, Media Queries and other techniques are critical. Take the following example :

In HTML5, there are several additions to the number of valid HTML tags.

	<header id="top" role="banner">
	<h1><a href="/">
		<img src="i/c/spring/logo.png" alt="Retreats 4 Geeks" />
	</a></h1>
	<nav role="navigation">
		<ol id="event-nav">
			<li id="nav-details">
				<a href="#details" title="Find out">Details</a>
			</li>
			<li id="nav-schedule">
				<a href="#schedule" title="Get over">Schedule</a>
			</li>
			<li id="nav-instructors">
				<a href="#instructors" title="Get facilitators">Instructors</a>
			</li>
			<li id="nav-lodging">
				<a href="#lodging" title="we  staying">Lodging</a>
			</li>
			<li id="nav-location">
				<a href="#location" title="Get the TN">Location</a>
			</li>
		</ol>
		<p id="nav-register">
			<b>Register Now</b>
			<span class="sold-out">Sold Out</span>
		</p>
	</nav>
</header>
<div id="content" class="vevent" role="main">

	<article id="details">
		<header>
			<h1>Join us for </h1>
			<p class="dates">
                            <time class="dtstart" datetime="2011-04-08" title="2011-04-08">8</time>&#8211;
                            <time class="dtend" datetime="2011-04-10" title="2011-04-10">10 April 2011</time></p>
			<p class="location">Gatlinburg, <abbr title="Tennessee">TN</abbr></p>
		</header>

		<figure class="frame focal">
			<img class="inner" src="i/mountains.jpg" alt="" title="Smoky Mountains"/>
		</figure>

		<section class="main description">
			<p class="intro">This Spring, Retreats 4 Geeks is proud to present three d.</p>
			<p>If you&#8217;re the kind of person who finds conference  to build incredible websites.</p>
			<ul>
				<li><strong>Top notch training:</strong>
					Retreats are comprised of </li>
				<li><strong>Learn from the experts:</strong>
					With more than 32 years of others.</li>
				<li><strong>Includes everything but airfare:</strong>
					You&#8217;re here to learn, not to worry about each day.</li>
				<li><strong>A fantastic location:</strong>
					Clearing your mind is the first step to learning,  Mountains</a>?</li>
			</ul>
		</section>
	</article><!-- / #details -->
</div>

Note the presence of HTML5 specific tags such as “header”, “article”, “section”, and “nav”. These are the markup tags you definitely want to become familiar with as you move forward with new web-based applications that may interface with mobile devices. Your new target should be HTML5, and HTML4 compatibility should be considered a secondary priority.

3) The overall budget impact of developing for HTML5 and supporting multiple browsers and hardware form-factors, depends on your teams training and experience in the area of supporting web standards, implementing media queries, and understanding tools that support these standards. ASP.NET MVC is in-place so that web developers may continue to implement compelling web applications and sites, utilizing their current expertise in .NET technologies, with the new HTML5 standard!

So if your team already uses ASP.NET MVC, the budgetary impact is negligible. If you decide that a desktop-type of website is all that is necessary for hardware of all shapes and sizes, then you are obviously able to eliminate any additional training or testing of the website at various screen-resolutions. In that case, your project budget will not be impacted at all.  However, if you feel that it’s important to support mobile phone and tablets as first-class citizens of the hardware/browser ecosystem that is the world-wide web, and your team is currently lacking training and/or experience in the field of “responsive design”, you will experience a slight increase in the first several projects that your organization undertake. The amount of increase will be roughly equivalent to the time it takes your team members to learn how to develop media queries, resize and float HTML elements properly depending on the media type, and implement HTML4 backward compatibility for all older browsers as necessary.

4) HTML5, CSS3, (specifically media queries and float/-webkit-transform-style/etc CSS tags), ASP.NET MVC, and JQuery/JSON/Javascript.

Posted in Mobile Development | Tagged , , | Comments Off

Entity Framework 4, WPF, and PropertyChanged event solution w/ T4-templating

While working on a relatively large WPF 4.0 project, I ran into a relatively common problem. The Entity-Framework doesn’t expose the “Property-Changed” event in all of the right places. Additionally, when I needed an “ObservableCollection” for updating a data-grid or list control of some type… I wasn’t provided with one out-of-the-box.

So enter T4-templates. What I did was definitely NOT a complete POCO class or “Repository pattern”. (Which you can learn more about here… “Using Repository Pattern with Entity Framework“) Instead, I simply wanted to expose the exact entities that EF 4.0 generates out-of-the-box… with some encapsulation classes that added “PropertyChanged” notifications and other useful things for my WPF project. This is REALLY useful because I can then make programmatic updates and see them reflected in the UI… regardless of whether I’m data-binding to a reference-type property of the entity-framework, or a scalar value-type property. Additionally, when I have an entity that contains a collection of sub-entities, I can now leverage the “ObservableCollection” concept to get the UI to automatically update if an item is programmatically added to the collection.

I guess the point here is to provide a stupid-simple way of turning any entity-framework EDMX file into a PropertyChanged/ObservableCollection aware series of Plain-Old-CLR-Object (POCO) entities whereby changes will still be able to be persisted back to the database via the “SaveChanges()” method and the WPF UI will update according to programmatic changes to the data.

So the T4-template is show below… and is also included as a link on this page. I know it’s only a fit for certain scenarios… but I tend to think it works well for simple scenarios. Simply change the file-name within the T4-template to point to your project’s EDMX file… and it will generate a series of “POCO” classes that encapsulate the functionality of the actual entity-classes for you.

Cool. Here’s the link…

[Note*** This T4 template distinguishes between some relationships in the EF model and others. It's selectively creating POCO classes and POCO class references depending on the multiplicity of the relationship between the entities. In other words... simple lookup-table relationships will not result in a POCO-class property data-type.]

Here’s the file contents :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
<#
//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Microsoft Public License.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
#>
<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#><#@
 output extension=".cs"#><#
 
CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
CodeRegion region = new CodeRegion(this, 1);
MetadataTools ef = new MetadataTools(this);
 
string inputFile = @"../YourEFModelHere.edmx";
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
string namespaceName = code.VsNamespaceSuggestion();
 
EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
 
// Write out support code to primary template output file
WriteHeader(fileManager);
BeginNamespace(namespaceName, code);
WriteCustomObservableCollection();
EndNamespace(namespaceName);
 
// Emit Entity Types
foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
{
	fileManager.StartNewFile(entity.Name + "Poco.cs");
 
	BeginNamespace(namespaceName, code);
	bool entityHasNullableFKs = entity.NavigationProperties.Any(np => np.GetDependentProperties().Any(p=>ef.IsNullable(p)));
#>
<#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#><#=code.StringBefore(" : ", code.Escape(entity.BaseType))#>Poco : INotifyPropertyChanged
{
 
<#region.Begin("Poco Initialization");#>
 
	private <#=code.Escape(entity)#> _context;
	private CollisionTransEntities _dbEntities;
	public <#=code.Escape(entity)#> Context{ get { return _context; } internal set { _context = value; } }
	public event PropertyChangedEventHandler PropertyChanged;
 
	public <#=code.Escape(entity)#>Poco()
    {
		_context = new <#=code.Escape(entity)#>();
		_context.PropertyChanged += context_PropertyChanged;
		Initialize(true);
	}
 
	public <#=code.Escape(entity)#>Poco(<#=code.Escape(entity)#> context, CollisionTransEntities dbEntities)
    {
        _context = context;
		DbEntities = dbEntities; 
		_context.PropertyChanged += context_PropertyChanged;
		Initialize(false);
    }
 
	private void Initialize(bool skipSubCollectionInitialization)
	{
<#
	foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
	{
		NavigationProperty inverse = ef.Inverse(navProperty);
		if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
		{
			WriteLine("		if (!skipSubCollectionInitialization)");
			WriteLine("			CreateNew" + navProperty.Name + "Collection();");
		}
		if ((inverse != null || ((AssociationType)navProperty.RelationshipType).IsForeignKey) &&
			navProperty.ToEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many)
        {
			WriteLine("		_context." + navProperty.Name + "Reference.AssociationChanged += " + navProperty.Name + "_AssociationChanged;");
		}
	}
#>
	}
 
	private void InitializeSubCollections()
	{
<#
	foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
	{
		NavigationProperty inverse = ef.Inverse(navProperty);
		if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
		{
			WriteLine("		CreateNew" + navProperty.Name + "Collection();");
		}
	}
#>
	}
 
	public CollisionTransEntities DbEntities
	{ 
		get
		{
			return _dbEntities;
		}
		set
		{
			if(_dbEntities == null)
			{
				_dbEntities = value;
				//Now also "Initialize" the sub-collections...
				InitializeSubCollections();
			}
		}
	}
 
	void context_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(e.PropertyName));
    }
 
<#region.End();#>
<#
    region.Begin("Primitive Properties");
 
    foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
    {
        bool isForeignKey = entity.NavigationProperties.Any(np=>np.GetDependentProperties().Contains(edmProperty));
        bool isDefaultValueDefinedInModel = (edmProperty.DefaultValue != null);
        bool generateAutomaticProperty = false;
 
 
 
#>
 
    <#=PropertyVirtualModifier(Accessibility.ForProperty(edmProperty))#> <#=code.Escape(edmProperty.TypeUsage)#> <#=code.Escape(edmProperty)#>
    {
<#
        if (isForeignKey)
        {
#>
		<#=code.SpaceAfter(Accessibility.ForGetter(edmProperty))#>get { return _context.<#=code.Escape(edmProperty)#>; } //qwer1 Type:<#=code.Escape(edmProperty.TypeUsage)#>
		<#=code.SpaceAfter(Accessibility.ForSetter(edmProperty))#>set 
		{ 
			if(_context.<#=code.Escape(edmProperty)#> != value)
			{
				_context.PropertyChanged -= context_PropertyChanged;
				_context.<#=code.Escape(edmProperty)#> = value;
				_context.PropertyChanged += context_PropertyChanged;
				if (PropertyChanged != null)
					PropertyChanged(this, new PropertyChangedEventArgs("<#=code.Escape(edmProperty)#>"));
				<#=entityHasNullableFKs?"//Entity property has nullable-FKs":""#>
			}
		}
<#
        }
        else if (isDefaultValueDefinedInModel)
        {
#>
        <#=code.SpaceAfter(Accessibility.ForGetter(edmProperty))#>get qwer2{ return <#=code.FieldName(edmProperty)#>; }
        <#=code.SpaceAfter(Accessibility.ForSetter(edmProperty))#>set { <#=code.FieldName(edmProperty)#> = value; }
<#
        }
        else
        {
            generateAutomaticProperty = true;
#>
		<#=code.SpaceAfter(Accessibility.ForGetter(edmProperty))#>get { return _context.<#=code.Escape(edmProperty)#>; } //qwer3 Type:<#=code.Escape(edmProperty.TypeUsage)#>
		<#=code.SpaceAfter(Accessibility.ForSetter(edmProperty))#>set 
		{ 
			if(_context.<#=code.Escape(edmProperty)#> != value)
			{
				_context.PropertyChanged -= context_PropertyChanged;
				_context.<#=code.Escape(edmProperty)#> = value;
				_context.PropertyChanged += context_PropertyChanged;
				if (PropertyChanged != null)
					PropertyChanged(this, new PropertyChangedEventArgs("<#=code.Escape(edmProperty)#>"));
			}
		}
<#
        }
#>
    }
 
<#
        if (!generateAutomaticProperty)
        {
#>
<#
        }
    }
    region.End();
 
    region.Begin("Complex Properties");
 
    foreach(EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity))
    {
#>
 
    <#=PropertyVirtualModifier(Accessibility.ForProperty(edmProperty))#> <#=code.Escape(edmProperty.TypeUsage)#> <#=code.Escape(edmProperty)#>
    {
        <#=code.SpaceAfter(Accessibility.ForGetter(edmProperty))#>get dfgh{ return <#=code.FieldName(edmProperty)#>; }
        <#=code.SpaceAfter(Accessibility.ForSetter(edmProperty))#>set { <#=code.FieldName(edmProperty)#> = value; }
    }
    private <#=code.Escape(edmProperty.TypeUsage)#> <#=code.FieldName(edmProperty)#> = new <#=code.Escape(edmProperty.TypeUsage)#>();
<#
    }
 
    region.End();
 
    ////////
    //////// Write Navigation properties -------------------------------------------------------------------------------------------
    ////////
 
    region.Begin("Navigation Properties");
 
    foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
    {
        NavigationProperty inverse = ef.Inverse(navProperty);
        if (inverse != null &&  !IsReadWriteAccessibleProperty(inverse))
        {
            inverse = null;
        }
#>
 
<#
        if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
        {
#>
    <#=PropertyVirtualModifier(Accessibility.ForReadOnlyProperty(navProperty))#> ObservableCollection<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>Poco> <#=code.Escape(navProperty)#>
    {
        get //qwer4
        {
            CreateNew<#=code.Escape(navProperty)#>Collection();
            return <#=code.FieldName(navProperty)#>;
        }
        set
        {
<#
            if (inverse != null || ((AssociationType)navProperty.RelationshipType).IsForeignKey)
            {
#>
            if (!Object.ReferenceEquals(<#=code.FieldName(navProperty)#>, value))
            {
				CreateNew<#=code.Escape(navProperty)#>Collection();
            }
<#
            }
            else
            {
#>
            CreateNew<#=code.Escape(navProperty)#>Collection();
<#
            }
#>
 
			if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("<#=code.Escape(navProperty)#>"));
        }
    }
    private ObservableCollection<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>Poco> <#=code.FieldName(navProperty)#>;
 
	private void CreateNew<#=code.Escape(navProperty)#>Collection()
    {
        if (<#=code.FieldName(navProperty)#> == null && _context.<#=code.Escape(navProperty)#> != null)
        {
            <#=code.FieldName(navProperty)#> = new ObservableCollection<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>Poco>();
			IEnumerable<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>> efEntities = DbEntities.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Unchanged | EntityState.Deleted).Where(i => i.Entity is <#=code.Escape(navProperty.ToEndMember.GetEntityType())#>).Select(i => i.Entity).Cast<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>>();
            foreach (var item in efEntities)
                <#=code.FieldName(navProperty)#>.Add(new <#=code.Escape(navProperty.ToEndMember.GetEntityType())#>Poco(item, DbEntities));
 
			//This will handle changes originating from the db-entities...
            _context.<#=code.Escape(navProperty)#>.AssociationChanged -= <#=code.Escape(navProperty)#>_AssociationChanged;
            _context.<#=code.Escape(navProperty)#>.AssociationChanged += <#=code.Escape(navProperty)#>_AssociationChanged;
 
			//This will handle changes originating from the User-Interface...
            <#=code.FieldName(navProperty)#>.CollectionChanged -= <#=code.Escape(navProperty)#>Collection_CollectionChanged;
            <#=code.FieldName(navProperty)#>.CollectionChanged += <#=code.Escape(navProperty)#>Collection_CollectionChanged;
        }
		else if (<#=code.FieldName(navProperty)#> != null && _context.<#=code.Escape(navProperty)#> == null)
			<#=code.FieldName(navProperty)#> = null;
    } 
 
	void <#=code.Escape(navProperty)#>Collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null && e.NewItems.Count > 0)
		{
            _context.<#=code.Escape(navProperty)#>.AssociationChanged -= <#=code.Escape(navProperty)#>_AssociationChanged;
            foreach (var newItem in e.NewItems)
                _context.<#=code.Escape(navProperty)#>.Add((newItem as <#=code.Escape(navProperty.ToEndMember.GetEntityType())#>Poco).Context);
			_context.<#=code.Escape(navProperty)#>.AssociationChanged += <#=code.Escape(navProperty)#>_AssociationChanged;
		}
        else if(e.OldItems != null && e.OldItems.Count > 0)
		{
            _context.<#=code.Escape(navProperty)#>.AssociationChanged -= <#=code.Escape(navProperty)#>_AssociationChanged;
            foreach (var removedItem in e.OldItems)
                _dbEntities.DeleteObject((removedItem as <#=code.Escape(navProperty.ToEndMember.GetEntityType())#>Poco).Context);
			//_context.<#=code.Escape(navProperty)#>.Remove((removedItem as <#=code.Escape(navProperty.ToEndMember.GetEntityType())#>Poco).Context);
			_context.<#=code.Escape(navProperty)#>.AssociationChanged += <#=code.Escape(navProperty)#>_AssociationChanged;
		}
    }
 
	void <#=code.Escape(navProperty)#>_AssociationChanged(object sender, CollectionChangeEventArgs e)
    {
        <#=code.Escape(navProperty.ToEndMember.GetEntityType())#> elem = e.Element as <#=code.Escape(navProperty.ToEndMember.GetEntityType())#>;
        if (elem != null)
        {
            if (e.Action == CollectionChangeAction.Add)
			{
				this.<#=code.FieldName(navProperty)#>.CollectionChanged -= <#=code.Escape(navProperty)#>Collection_CollectionChanged;
                this.<#=code.FieldName(navProperty)#>.Add(new <#=code.Escape(navProperty.ToEndMember.GetEntityType())#>Poco(elem, DbEntities));
				this.<#=code.FieldName(navProperty)#>.CollectionChanged += <#=code.Escape(navProperty)#>Collection_CollectionChanged;
			}
            else if (e.Action == CollectionChangeAction.Remove)
			{
				this.<#=code.FieldName(navProperty)#>.CollectionChanged -= <#=code.Escape(navProperty)#>Collection_CollectionChanged;
				<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>Poco pocoToRemove = this.<#=code.FieldName(navProperty)#>.Where(i => i.Context.Equals(elem)).SingleOrDefault();
                this.<#=code.FieldName(navProperty)#>.Remove(pocoToRemove); 
				this.<#=code.FieldName(navProperty)#>.CollectionChanged += <#=code.Escape(navProperty)#>Collection_CollectionChanged;
			}
            else if (e.Action == CollectionChangeAction.Refresh)
            {
				<#=code.FieldName(navProperty)#>.CollectionChanged -= <#=code.Escape(navProperty)#>Collection_CollectionChanged;
                new List<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>Poco>(<#=code.FieldName(navProperty)#>).ForEach(i => <#=code.FieldName(navProperty)#>.Remove(i));
				<#=code.FieldName(navProperty)#>.CollectionChanged += <#=code.Escape(navProperty)#>Collection_CollectionChanged;
 
				IEnumerable<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>> efEntities = DbEntities.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Unchanged | EntityState.Deleted).Where(i => i.Entity is <#=code.Escape(navProperty.ToEndMember.GetEntityType())#>).Select(i => i.Entity).Cast<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>>();
                foreach (var item in efEntities)
                    <#=code.FieldName(navProperty)#>.Add(new <#=code.Escape(navProperty.ToEndMember.GetEntityType())#>Poco(item, DbEntities));
 
				_context.<#=code.Escape(navProperty)#>.AssociationChanged -= <#=code.Escape(navProperty)#>_AssociationChanged;
                _context.<#=code.Escape(navProperty)#>.AssociationChanged += <#=code.Escape(navProperty)#>_AssociationChanged;
            }
        }
    }
 
<#
        }
        else
        {
#>
    <#=PropertyVirtualModifier(Accessibility.ForProperty(navProperty))#> <#=code.Escape(navProperty.ToEndMember.GetEntityType())#> <#=code.Escape(navProperty)#>
    {
<#
            if (inverse != null || ((AssociationType)navProperty.RelationshipType).IsForeignKey)
            {
#>
		<#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get { return _context.<#=code.Escape(navProperty)#>; } //dfgh2 Type:<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>
        <#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set
		{  
			if (!Object.ReferenceEquals(_context.<#=code.Escape(navProperty)#>, value))
            {
				_context.<#=code.Escape(navProperty)#>Reference.AssociationChanged -= <#=code.Escape(navProperty)#>_AssociationChanged;
				_context.<#=code.Escape(navProperty)#> = value;
				_context.<#=code.Escape(navProperty)#>Reference.AssociationChanged += <#=code.Escape(navProperty)#>_AssociationChanged;
				if (PropertyChanged != null)
					PropertyChanged(this, new PropertyChangedEventArgs("<#=code.Escape(navProperty)#>"));
			}
		}
    }
 
	void <#=code.Escape(navProperty)#>_AssociationChanged(object sender, CollectionChangeEventArgs e)
    {
			if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("<#=code.Escape(navProperty)#>"));
	}
<#
            }
            else
            {
#>
        <#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get dfgh3;
        <#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set;
    }
<#
            }
        }
    }
    region.End();
 
    region.Begin("Association Fixup");
 
 
    region.End();
#>
}
<#
    EndNamespace(namespaceName);
}
 
foreach (ComplexType complex in ItemCollection.GetItems<ComplexType>().OrderBy(e => e.Name))
{
    fileManager.StartNewFile(complex.Name + ".cs");
    BeginNamespace(namespaceName, code);
#>
<#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#>
{
<#
    region.Begin("Primitive Properties");
 
    foreach(EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex))
    {
        bool isDefaultValueDefinedInModel = (edmProperty.DefaultValue != null);
#>
 
    <#=Accessibility.ForProperty(edmProperty)#> <#=code.Escape(edmProperty.TypeUsage)#> <#=code.Escape(edmProperty)#>
<#
        if (isDefaultValueDefinedInModel)
        {
#>
    {
        <#=code.SpaceAfter(Accessibility.ForGetter(edmProperty))#>get dfgh4{ return <#=code.FieldName(edmProperty)#>; }
        <#=code.SpaceAfter(Accessibility.ForSetter(edmProperty))#>set { <#=code.FieldName(edmProperty)#> = value; }
    }
    private <#=code.Escape(edmProperty.TypeUsage)#> <#=code.FieldName(edmProperty)#><#=code.StringBefore(" = ", code.CreateLiteral(edmProperty.DefaultValue))#>;
<#
        }
        else
        {
#>
    {
        <#=code.SpaceAfter(Accessibility.ForGetter(edmProperty))#>get dfgh5;
        <#=code.SpaceAfter(Accessibility.ForSetter(edmProperty))#>set;
    }
<#
        }
    }
 
    region.End();
 
    region.Begin("Complex Properties");
 
    foreach(EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex))
    {
#>
 
    <#=Accessibility.ForProperty(edmProperty)#> <#=code.Escape(edmProperty.TypeUsage)#> <#=code.Escape(edmProperty)#>
    {
        <#=code.SpaceAfter(Accessibility.ForGetter(edmProperty))#>get dfgh6{ return <#=code.FieldName(edmProperty)#>; }
        <#=code.SpaceAfter(Accessibility.ForSetter(edmProperty))#>set { <#=code.FieldName(edmProperty)#> = value; }
    }
    private <#=code.Escape(edmProperty.TypeUsage)#> <#=code.FieldName(edmProperty)#> = new <#=code.Escape(edmProperty.TypeUsage)#>();
<#
    }
 
    region.End();
#>
}
<#
    EndNamespace(namespaceName);
}
 
if (!VerifyTypesAreCaseInsensitiveUnique(ItemCollection))
{
    return "";
}
 
fileManager.Process();
 
#>
<#+
void WriteHeader(EntityFrameworkTemplateFileManager fileManager, params string[] extraUsings)
{
    fileManager.StartHeader();
#>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template written by Chad W. Stoker.
//	   10/18/2011
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
 
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Data;
using System.ComponentModel;
 
<#=String.Join(String.Empty, extraUsings.Select(u => "using " + u + ";" + Environment.NewLine).ToArray())#>
<#+
    fileManager.EndBlock();
}
 
void BeginNamespace(string namespaceName, CodeGenerationTools code)
{
    CodeRegion region = new CodeRegion(this);
    if (!String.IsNullOrEmpty(namespaceName))
    {
#>
namespace <#=code.EscapeNamespace(namespaceName)#>
{
<#+
        PushIndent(CodeRegion.GetIndent(1));
    }
}
 
 
void EndNamespace(string namespaceName)
{
    if (!String.IsNullOrEmpty(namespaceName))
    {
        PopIndent();
#>
}
<#+
    }
}
 
bool IsReadWriteAccessibleProperty(EdmMember member)
{
    string setter = Accessibility.ForWriteOnlyProperty(member);
    string getter = Accessibility.ForReadOnlyProperty(member);
 
    return getter != "private" && getter != "protected" && setter != "private" && setter != "protected";
}
 
string PropertyVirtualModifier(string accessibility)
{
    return accessibility + (accessibility != "private" ? " virtual" : "");
}
 
void WriteCustomObservableCollection()
{
#>
// An System.Collections.ObjectModel.ObservableCollection that raises
// individual item removal notifications on clear and prevents adding duplicates.
public class FixupCollection<T> : ObservableCollection<T>
{
    protected override void ClearItems()
    {
        new List<T>(this).ForEach(t => Remove(t));
    }
 
    protected override void InsertItem(int index, T item)
    {
        if (!this.Contains(item))
        {
            base.InsertItem(index, item);
        }
    }
}
<#+
}
 
bool VerifyTypesAreCaseInsensitiveUnique(EdmItemCollection itemCollection)
{
    Dictionary<string, bool> alreadySeen = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
    foreach(StructuralType type in itemCollection.GetItems<StructuralType>())
    {
        if (!(type is EntityType || type is ComplexType))
        {
            continue;
        }
 
        if (alreadySeen.ContainsKey(type.FullName))
        {
            Error(String.Format(CultureInfo.CurrentCulture, "This template does not support types that differ only by case, the types {0} are not supported", type.FullName));
            return false;
        }
        else
        {
            alreadySeen.Add(type.FullName, true);
        }
 
    }
 
    return true;
}
#>
Posted in Entity Framework, Gotchas, WPF | Tagged , , , | Comments Off

Our Capabilities Include:


Custom Software Development
Enterprise Architecture
Project Management
Systems Analysis
Performance Testing

AND THE LIST GOES ON...

These methods are vital to our work:


Agile Methodology
PMBOK
Test-Driven Development

LEARN WHY...

About CodeSmart, Inc.


CodeSmart has been locally owned and operated in the Olympia, WA area since 2002. We direct, design, develop and deliver full end-to-end information systems using leading edge Microsoft .Net technologies and recommended best practices.

LEARN MORE...