Friday, April 20, 2012

How To: Add a new Content Database in SharePoint 2010

You can use the procedures that are described in this article to create a new content database and attach it to a Web application.

In this article:

  • To add a content database to a Web application by using Central Administration

  • To add a content database to a Web application by using Windows PowerShell

To add a content database to a Web application by using Central Administration

  1. Verify that the user account that is being used to perform this operation is a member of the Farm Administrators SharePoint group. If you are using Windows authentication to connect to SQL Server, the user account must also be a member the SQL Server dbcreator fixed server role on the SQL Server instance where the database will be created. If you are using SQL authentication to connect to SQL Server, the SQL authentication account that you specify when you create the content database must have dbcreator permission on the SQL Server instance where the database will be created.
  2. On the SharePoint Central Administration Web site, click Application Management.
  3. In the Databases section, click Manage content databases.
  4. On the Manage Content Databases page, click Add a content database.
  5. On the Add Content Database page:


    1. Specify a Web application for the new database.

    2. Specify a database server to host the new database.

    3. Specify the authentication method that the new database will use and supply an account name and password, if they are necessary.


      Important:
      The account name and password must already exist as a SQL Server login.
    4. Specify the name of the failover database server, if one exists.

    5. Specify the number of top-level sites that can be created before a warning is issued. By default, this is 9,000.

    6. Specify the total number of top-level sites that can be created in the database. By default, this is 15,000.


      Note:
      For information about how to determine the number of top-level sites that the system can support, see Performance and capacity technical case studies (SharePoint Server 2010).
    7. Click OK.

To add a content database to a Web application by using Windows PowerShell

  1. Verify that you meet the following minimum requirements: See Add-SPShellAdmin. If you are using Windows authentication to connect to SQL Server, the user account must also be a member the SQL Server dbcreator fixed server role on the SQL Server instance where the database will be created. If you are using SQL authentication to connect to SQL Server, the SQL authentication account that you specify when you create the content database must have dbcreator permission on the SQL Server instance where the database will be created.
  2. On the Start menu, click Administrative Tools.
  3. Click SharePoint 2010 Management Shell.
  4. At the Windows PowerShell command prompt, type the following command:

    New-SPContentDatabase -Name  -WebApplication 
    Where is the name of the content database to create and is the name of the Web application to which the new database is attached.
    For more information, see New-SPContentDatabase.

Managing SharePoint Projects Part 1 - Requirements Gathering and Analysis

Managing SharePoint Projects Part 1 - Requirements Gathering and Analysis, talks about the art of gathering & analyzing requirements for SharePoint projects.

In this post, I share my industry experience in handling customers, gathering requirements, setting expectations right and documenting requirements, so as to do things right the first time.

1. Project Roles/Structure:
The Business Development officer/Sales rep gets the project for the organization, he knows "What SharePoint can do and how it fits in the client requirements", he bids and gets the contract for the company, then interacts with the Delivery Manager to get the project done.

The Delivery manager has many projects to deliver under his department/region umbrella, so he passes it on to the Project Manager and gives him full authority and control over the project.

The Project manager has a SharePoint team in place to implement SharePoint projects. the team structure for a medium to large project implementation ideally comprises of a SharePoint Solution Architect, SharePoint Admin/Infrastructure team, Team/Project lead, a Test lead or Testing team and finally SharePoint team members for project implementation.

Again the above team composition is Project specific, in cases of small project implementations I have seen SharePoint developers playing all the above mentioned roles under the guidance of a team lead and project manager successfully.

2. Role-Responsibility:  Here is the roles-responsibilities mapping details:

  • Business Development Lead/Sales Rep - Managing Contracts, RFP's, High level bid estimates
  • Delivery Lead - Responsible for Project execution, has many projects under his umbrella.
  • Project Manager - Resource mobilization, Project Management activities include: Project Planning, Estimation, Risk management, Client interfacing, Co-ordination, Control and getting things done. Needs to create Business Requirements Document.
  • Project/Team Lead - Gathering/understanding requirements from the client, constant customer interaction/communication for clarifications, project progress, team meetings, progress/status checks, prevent effort/schedule slippage, may also play a part in the project estimation. Needs to create Software Requirements Specification and Use Case documents along with Use Case Diagrams.
  • SharePoint Solution Architect - Technical Architecture/Solution, Tools/Technology evaluation, Capacity Management, Hardware sizing, Farm scaling, High level and Detailed level technical diagrams
  • SharePoint Developer - Developer is responsible for actual technical implementation, creation of deployment scripts, unit test cases, code review (for custom features, infopath forms etc.), process/product quality, they might be additionally involved in Requirements Gathering or Estimation process.
  • SharePoint Admin/Infrastructure team - Responsible for SharePoint environment set-up, Configurations, Deployments, Back Up/Recovery, Disaster recovery, High Availability, Load balancing techniques like Network Load Balancing, Round Robin etc.
  • Test lead/Testing team - Responsible for System and Integration testing, creation of system/integration test cases, logging Defects/Bugs, discussion with development teams w.r.t to Product performance and quality.
Additionally there could be an organization specific Process Quality Group to measure and assess the project documents/artifacts vis-a-vis organization policies/standards.

3. Requirements Gathering and Analysis Participants:
Requirements Gathering & Analysis team can be formulated using the following permutations and combinations:
a. Project Manager and a Team Lead together
b. Team Lead and SharePoint Architect together
c. Team Lead and member/s of development team or
The above participants might be called as SharePoint Requirements SME(s)/Analyst(s).

For the sake of convenience, I will use the acronym RGA, which means Requirements Gathering Analyst(s) (can be an individual/group of individuals as mentioned above.)

4. Requirements Gathering and Analysis Techniques: 
The common techniques of gathering and analyzing SharePoint requirements are as follows:

a. Record your Discussions: Since RGA closely interfaces with the customer all the time, he needs to discuss with the customers, either face-to-face or live meetings or video conferencing. These discussions generally start with either their existing systems which they would like to re-engineer or migrate to SharePoint or a new system to be developed from scratch.

Its always a best practice to record these discussions in the background via some audio/video recording tool, in all cases make the customer aware that you are recording the sessions and get his approval before you do so. Firstly it is an important record/proof of what has been discussed and secondly you might want to re-visit for your own benefit.

Re-visit these recordings in case you are unclear or pass it on to the other team members parallely so that they have the feel of the project.

b. Dare to Ask Questions: Never assume things when gathering requirements, ask a lot of questions, let the communication be a two way process. Sometimes, you might interrupt and ask questions as well. I ask a lot of silly questions and get customer conformance as well.

Sometimes, there is a huge difference between what the customers literally say and what they actually mean. Like they would say as if they need only a Knowledge Management solution, but in reality they actually expect a Knowledge Management portal with Multi-lingual features, Advanced workflows, Advanced Reporting scenarios and other complexities as well.

The complexity and scope of project gets clarified only when you dare to ask questions.

c. Always Summarize: After each logical end of the discussion summarize your understanding and get customer conformance. In that way, you feel confident and customer is also happy that you have understood things properly.

d. Avoid unnecessary arguments:  Never argue with the customer unnecessarily, you may suggest but can't argue and put him off. That's not the objective. Remember Customer is always the king. Like it or not, but it is the ultimate truth. I have faced it a lot many times, when customer has made some sarcastic comments and I had to nod and take it in good humor.

e. Get to know the customer environment/policies: Especially with Banks & Financial Institutions, since they won't allow custom code, feature deployments, webparts etc in their SharePoint farm. Its always better to discuss this aspect in advance, as a lot of the requirements that you will discuss might need extensive customizations in SharePoint. In such a scenario, always mention it outright to your customers. There will always be a work-around process that involves communication between customers IT Infrastructure team and your team on the need to get custom dlls, features, web parts, third party tools etc. deployed in a safe and an effective manner.


f. Manage expectations: SharePoint is an over-hyped product, lots of customers have been tricked to believe that SharePoint can do everything out of the box. It is the job of RGA to set expectations right for the customer and communicate what can be done OOTB and what sections would need customization, I prefer to give them alternative options like third party tools, custom development as per the org environment policies etc and somehow try to create a Win-Win situation.

g. Wired frame diagrams/Proto-type: Its always a good practice to create wire-frame diagrams and get customer buy in. Proto-types are even more effective, but it all depends on the nature of requirements and time pressures. I prefer to make proto-types for complex projects, for lesser complex projects, Wired-frame screen diagrams would generally suffice.

h. Final Output: At the end of the day, what matters is the final output, the RGA should be effectively able to write a Business Requirements Document (BRD), Use Case Requirements Document, System Requirements Specifications document (SRS) and Requirements Tracking and Traceability (RTT) document.

i . Use Case Specifications document: Here we document the User-System interaction with appropriate Use Case diagrams, Preconditions, Post-conditions, Normal Flow and Alternative Flow.

ii. Business Requirements document (BRD): Here we document the Business Perspective/Business need. Use case ids are linked to each Business Requirement.

iii. System Requirements Specifications (SRS): System requirements is again the System requirements documented in detail, it links with the Use Case document and the BRD.


iv. Requirements Traceability Table (RTT): Its an excel sheet that maps the Business Requirements Ids with appropriate Use Case document ids and SRS ids. It will also map the Unit & System Test Case Ids for each Business Requirement ID.

Future posts: Managing SharePoint Projects Part 2 will cover Estimating SharePoint Projects, which will be an interesting post to watch out for, since there is no standard methodology like Function Points etc to estimate SharePoint projects.

Best Practices for developing Web Content Management (WCM) Portals using SharePoint 2010

Best Practices to consider while developing Web Content Management (WCM) portals using SharePoint 2010:

1. Prepare wired-frame diagrams for depicting screen layouts, developing a Proto-type in SharePoint is even better. It gives tremendous clarity to all the stakeholders and it becomes easy to communicate to your developers as well. Use Visio for this purpose.

2. Plan your web application topology well in advance. Identify when to use a site collection and when to use a subsite.

3. Define your taxonomies/folksonomy, use the SP 2010 managed metadata services.

4. Maintain separate content databases per  site collection, whenever you feel that your site collection can grow beyond 50 GB of data, move it into a separate content database, it becomes easier to manage and take back-ups and restore your web-application. SP 2010 recommended limit for content databases is a maximum of 100GB per site collection.

5. Always use content types, site columns for all your applications. Avoid creating columns directly in list/library.

6. Always limit the number of items in a List View using Filters.

7. Keep a very simple and a neat user interface with a user friendly navigation scheme.

8. Deploy your custom web parts, user controls, delegate controls, custom workflows as a feature solution package

9. Always prefer inheriting permissions for child sites, since they can be broken later.

10. Rigorously monitor your Application health using the new SP 2010 Developer dashboard for page response, memory leaks etc. ULS Diagnostic logging for errors etc.

11. Monitor your Content database size so that it does not exceed 100GB per site collection.

12. Use the new SP 2010 Folder Partitioning rules when your Document Library View items exceed the recommended 5000 item limit.

13. Always use Power Shell scripts to perform Solution installation, BackUp/Restore operations, Content database attach/detach, creating/deleting site collections and other Admin related operations.

14. Have atleast one Indexed column in your Lists for a performance reasons.

15. For moving content from staging to production environment, prefer using the new SQL Server 2008 Enterprise edition, Database snapshot technique which takes a quick snapshot of the Production farm and then ships it to the Destination farm.

16. You might convert your existing site collection to a solution file using SPD 2010 and open the solution using a Visual Studio 2010. and enhance it further. This is a faster way to build site definitions.

17. You can edit all List forms using InfoPath 2010, provided you have Enterprise edition of SP 2010. In this way you will be able to modify your New/Edit/Display forms using InfoPath 2010.

18. Use the advanced Record Management Rules for archiving, moving or marking documents as records. Alternatively InPlace records management is also available for declaring documents as records.

19. Prefer creating a Visual Webpart for better control over layout and ease of programming.

20. Prefer Creating Site Columns and Content Types programmatically over Features, the reason is when you add/update site columns in your custom content type, newly added/modified columns do not become immediately visible in the List/Page Content Type from the Parent Site Content Type.

SharePoint 2010 Enterprise Content/Web Content Management Features

New Enterprise Content Management (ECM) /Web Content Management (WCM) features in SharePoint 2010:


Ref #
Business Function
Description
1.   
Search
·         Interactive Search Experience – A richer search experience providing flexible navigation, refinement and related searches. Both Standard and FAST Search for SharePoint get query completion, spell checking, wild cards and more.
·         FAST Search - Seamless integration with FAST Search enhances the search experience enabling feature content for common queries and providing more flexible navigation and document thumbnails and previews including in slide navigation of PowerPoint presentations which is a common end user scenario.
·         Relevance – Search includes Out-of-box ranking and relevance factors including social data such as tagging and usage (clicks). FAST Search adds more configurable set of relevance inputs for custom applications and specialized corpuses.
·         People Search – People finding based on social networking and expertise algorithms and tailored user experience for people including getting views of authored content. As users frequently do not know or recall the spelling of people’s names, search includes a new phonetic search algorithm that works much better than previous approaches to spell checking for names.
·         Connectivity For data that lives outside SharePoint, search is expanded and improved with connectors to index web sites, file servers, SharePoint, Exchange, Lotus Notes, Documentum and FileNet. The updated Business Connectivity Services (previously the BDC) described below makes it much easier to index an arbitrary source such as a custom database. You can create this search connection without code using the new SharePoint Designer.
·         Scale and Platform Flexibility – Significant performance and scalability improvements through the new search technology. It also includes partitioned indices and scale-out query servers in SharePoint search. FAST scales-out even further and has significantly more pipeline extensibility to handle the largest collections and most complex value-added processing and search applications. The new capabilities support hundreds of millions of documents with great index freshness and query latency.
2.   
Metadata
·         Managed Metadata - Companies often require the use of approved terms from a centrally controlled taxonomy. The SharePoint 2010 response is managed metadata, which is the ability to create, manage, and publish term sets across the enterprise from a single point of reference.
·         Term sets - Term sets are hierarchical trees, internally connected structures that display parent-child relationships. Term sets and content type galleries are available to any site collection that can securely access the url for the managed metadata service.
·         Folders based metadata- Folders are now first-class objects in SP 2010. Documents and subfolders can inherit metadata from their parent folder making it easier to find documents when metadata is automatically added, instead of forcing users to add the same value over and over to the hundred documents they just uploaded.
3.   
Document Management & Classification
SharePoint 2010 adds scale and depth in the areas of Enterprise Content Management well advancing the user experience. ECM features are as follows:
·         Large Lists and Libraries – Support for much larger document libraries with metadata driven navigation to help users go quickly to the content that is most important to them. Libraries will scale to tens of millions and archives to hundreds of millions of documents. This is a key investment for high-end document and records management but also helps organizations with lots of smaller sites. Enhancement of the workflow capabilities and tools in SharePoint Designer.
·         Enterprise Metadata – Support for enterprise wide content types and taxonomies not only across sites but also server farms. Applying this metadata is made easy (and valuable to users) in both the SharePoint and Office client user experience. The top-down taxonomy and bottoms-up social tagging (sometimes called folksonomy) combine to help improve search, navigation and people connections.
·         Document Sets – A new way to manage a collection of documents as a single object for workflow, metadata, etc. within SharePoint and Office so experience more closely models your work product (e.g. a proposal that may contain a presentation, budget, contract, etc.).
·         Web Publishing including Digital Asset Management – A number of key improvements to make it easier to publish rich sites on the intranet or internet. The new browser ribbon and editor experience to speed site customization, content authoring and publishing tasks. Support for digital asset management features like thumbnails, metadata and ratings for images as well as video streaming from SharePoint.  Improved content deployment robustness from authoring to production for larger scale sites.
·         Governance and Records Management – Compliance is an increasingly important requirement for organizations. Enhanced Records Managements features in 2010 building on the scalable storage and enterprise metadata support described above. Just a few new features include location-based file plans, multi-stage dispositions, in-place records and e-discovery.
·         Social Feedback and Organization – SharePoint 2010 provides a consistent experience for organizing, finding and staying connected to information and people including bookmarks, tagging and ratings. It encompasses a new holistic approach across search, navigation, profiles, feeds and more. Bringing together informal social tagging with formal taxonomy described below so you can choose the right approach for a given set of content.
·         SharePoint Mobile Access – Improved the experience for mobile web browsers and are introducing a new SharePoint Workspace Mobile client so you can take Office content from SharePoint offline on a Windows Mobile device. These clients let you navigate lists and libraries, search content and people and even view and edit Office content within the Office Web App experience running on a mobile browser.
·         Content organizer - Content organization is largely a matter of individual upload decisions. Administrators could help guide those decisions, but ultimately, it was up to the contributors to decide where the content ended up. The new Content Organizer allows routing decisions to be centrally organized. It takes these decisions out of the hands of users and ensures that items are well organized. Users are guided to enter appropriate metadata rather than being allowed to dump documents wherever they like.
4.   
Audit
·         Granular Lists, Libraries, and Sites audit management – Granular Audit management/logging settings enables you to track opening or downloading documents, viewing items in lists, or viewing item properties, editing items, checking out or checking in items,
moving or copying items to another location in the site, deleting or restoring items. Includes editing content types and columns,
searching site content, editing users and permissions .
·         Audit Log Trimming - You also have the ability in 2010 to enable Audit Log Trimming which includes storing the current audit data in a Document Library.
·         ULS logs - ULS is improved through several facets including the introduction of a new and extensible Logging database, configurable noise suppression (Event Log Flood Protection), throttling, correlation Ids, and control of the amount of disk space used by logs as well as native compression of said logs - at the end of the day you can expect an approximate 50% savings in size of ULS logs as a result.
5.   
Workflow Management
·         Site and List level association - SharePoint 2010 workflow instances can be associated with a list item or a site.  
·         Reusable workflows - Reusable workflow points to content type (including base item content type), so it can be associated with any list. You need to prudent on associating the workflow to content type as content type associated columns will be available to the workflow.
·         Document Sets - Associate workflows with multiple documents using the new content type: Document Set (basically it is collection of documents).
·         Integration with Visio - Workflow can be imported and exported between SharePoint Designer and Visio. Visio only allows Sequential workflows. Stencils in Visio will have conditions, actions and connectors. Saves as standard Visio (.vsd) file. File menu allows export to workflow file (.vdi) file which is a compacted set of “xoml” file.
·         SharePoint Designer (SPD) Enhancements
a. Allows you to export as WSP or solution package. Can use .aspx or InfoPath forms in the workflow. Nested actions – step inside a step, conditional logic statements, look ups etc. Out-of-the box workflows (like Approval Workflow) is configurable using SPD. SPD allows you to create Workflow tasks.
b. Approval Workflow is configurable using SPD. SPD allowing you to create Workflow tasks.
c. Easy to create no-code workflow solutions with built-in ready-to-use workflow activities.

Trying to use an SPWeb object that has been closed or disposed and is no longer valid.

"Trying to use an SPWeb object that has been closed or disposed and is no longer valid" error message is very common amongst developers dealing with the SharePoint object model. Here is how the error looks like:



The reason behind this is a silly mistake that developers do, when trying to use the SPSite/SPWeb objects. Here is the bad code that resulted in the error:



I used the using clause alongwith the SPContext.Current.Site which resulted in this error, it implicilty disposes the SPSite object which should not be done when using the SPContext object. Lets refactor the code a little bit and have a look at the good code snippet which resolved this issue:



Thats about it, my code started working when I removed the using clause from the SPContext.Current.Site. The same thing is true when you try to either explicitly/implicitly Dispose the SPContext.Current.Web object. So moral of the story never dispose SPContext objects either implicitly leveraging the using clause or explicitly by using Dispose method from in your finally block.

SharePoint 2010 - Do not dispose guidance for SharePoint objects

Do not dispose the following listed SharePoint objects explicitly: (Applicable for both SharePoint 2010 and SharePoint 2007)

•SPContext.Current.Site

•SPContext.Current.Web

•SPContext.Site

•SPContext.Web

•SPControl.GetContextWeb(..)

•SPControl.GetContextSite(..)

•SPFeatureReceiverProperties.Feature.Parent

•SPItemEventProperties.ListItem.Web

•SPList.BreakRoleInheritance()

◦Do not call list.ParentWeb.Dispose()

•SPListEventProperties.Web

•SPListEventProperties.List.Web

•SPSite.RootWeb

◦Problems may occur when SPContext.Web has equality to the SPContext.Web.. make sure you dispose of SPSite and it will cleanup sub webs automatically

•SPSite.LockIssue

•SPSite.Owner

•SPSite.SecondaryContact

•SPWeb.ParentWeb

•SPWebEventProperties.Web

Few important changes for Dispose rules in SharePoint 2010:
•Microsoft.SharePoint.WebControls.SiteAdminsitrationSelector.CurrentItem
When used with WSS 3.0 you must call Dispose(), with SharePoint Foundation 2010 you don’t.

•Event Receivers and properties.OpenWeb()
WSS 3.0: When you call properties.OpenWeb() the returned SPWeb will need to call Dispose()
SharePoint Foundation 2010: Use the newly introduced SPItemEventProperties.Web property instead of SPItemEventProperties.OpenWeb() for better performance and to avoid the need to call Dispose().

Reference: http://blogs.msdn.com/b/rogerla/archive/2009/11/30/sharepoint-2007-2010-do-not-dispose-guidance-spdisposecheck.aspx

SPSecurity.RunWithElevatedPrivileges Access denied issue

SPRunWithElevatedPrivileges allows you to run your SharePoint code in the context of the App Pool identity account.

Look at the piece of code below:


function void ListItemUpdate(Guid guId)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPSite site = SPContext.Current.Site;
SPWeb web = SPContext.Current.Web;
web.AllowUnsafeUpdates = true;

SPList list = web.Lists["Products"];
SPListItem item = list.Items[guId];
item["ProductName"] = "Apple iPhone 4";
item["ProductPrice"] = "199";

item.Update();

web.AllowUnsafeUpdates = false;
});
}

So when a user with Read access tries to execute the above code, he gets an Access denied error, even after the code having the RunWithElevated Privileges set.

Lets examine, look at the code highlighted in yellow above. SPContext.Current.Site and SPContext.Current.Web runs the List Item update code in the context of the currently logged in user and not in the context of the App Pool identity.

Solution: Solution is to re-open new SPSite and SPWeb objects within the SPSecurity delegate block, lets rewrite the above code and fix the issue:

function void ListItemUpdate(Guid guId)
{
Guid siteId = SPContext.Current.Site.Id;
Guid webId = SPContext.Current.Web.Id;

SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(siteId))
{
using (SPWeb web = site.OpenWeb(webId))
{
web.AllowUnsafeUpdates = true;

SPList list = web.Lists["Products"];
SPListItem item = list.Items[guId];
item["ProductName"] = "Apple iPhone 4";
item["ProductPrice"] = "199";
item.Update();

web.AllowUnsafeUpdates = false;
}
}
});
}

Running this piece of code fixes the Access denied issue and allows the code to run under AppPool identity.

Thursday, April 12, 2012

Create a Multiple-Column Lookup

The following example shows the complete code for a subclass of the SPFeatureReceiver class that creates and deletes lookup columns on the Contoso Orders list. Code in the FeatureActivated method creates a primary lookup column named Customer ID that looks up the value of the ID column on the Contoso Customers list. The code then creates secondary lookup columns for First Name, Last Name, and Phone, and it adds the secondary columns to the default view on the Contoso Orders list.
The example also includes code for the FeatureDeactivating method, which deletes all the lookup columns that are created in the FeatureActivated method. Note that you must delete all secondary lookup columns before you delete the primary lookup column on which they depend.

using System;
using System.Runtime.InteropServices;
using Microsoft.SharePoint;

namespace Contoso.Orders.Features.CustomerLookups
{
    [Guid("49e72c4b-cfcb-4665-9c2a-fdadf0a3b018")]
    public class CustomerLookupsEventReceiver : SPFeatureReceiver
    {

        // Define static field names.
        const string STATIC_CUST_ID = "CustID";
        const string STATIC_CUST_FNAME = "CustFName";
        const string STATIC_CUST_LNAME = "CustLName";
        const string STATIC_CUST_PHONE = "CustPhone";

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            string logEntry = properties.Definition.DisplayName + " activation error: ";

            // Get an object representing either the current website (if the scope is Web)
            // or the root website (if the scope is Site).
            SPWeb web = properties.Feature.Parent as SPWeb;
            if (web == null)
            {
                SPSite site = properties.Feature.Parent as SPSite;
                if (site != null)
                    web = site.RootWeb;
            }
            if (web == null)
            {
                System.Diagnostics.Trace.WriteLine(logEntry + "Invalid scope");
                return;
            }

            // Get objects for the two lists.
            SPList customers = web.Lists.TryGetList("Contoso Customers");
            SPList orders = web.Lists.TryGetList("Contoso Orders");
            if (customers == null || orders == null)
            {
                System.Diagnostics.Trace.WriteLine(logEntry + "List not found");
                return;
            }

            // Get the fields from the Customers list that will be seen on the Orders list.
            SPField custID, custLName, custFName, custPhone;
            try
            {
                custID = customers.Fields.GetField("ID");
                custFName = customers.Fields.GetField("First Name");
                custLName = customers.Fields.GetField("Last Name");
                custPhone = customers.Fields.GetField("Contact Phone");
            }
            catch (ArgumentException ex)
            {
                // One of the fields was not found on the Customers list.
                System.Diagnostics.Trace.WriteLine(logEntry + ex.Message);
                return;
            }

            /* 
            * Create a multi-column lookup on the Orders list. 
            */

            // Create the primary column: Customer ID.
            string strPrimary = orders.Fields.AddLookup("Customer ID", customers.ID, true);

            SPFieldLookup primary = orders.Fields.GetFieldByInternalName(strPrimary) as SPFieldLookup;
            primary.LookupField = custID.InternalName;
            primary.StaticName = STATIC_CUST_ID;
            primary.Update();

            // Create a secondary column: First Name.
            string strFName = orders.Fields.AddDependentLookup("First Name", primary.Id);

            SPFieldLookup ordersFName = orders.Fields.GetFieldByInternalName(strFName) as SPFieldLookup;
            ordersFName.LookupField = custFName.InternalName;
            ordersFName.StaticName = STATIC_CUST_FNAME;
            ordersFName.Update();

            // Create a secondary column: Last Name.
            string strLName = orders.Fields.AddDependentLookup("Last Name", primary.Id);

            SPFieldLookup ordersLName = orders.Fields.GetFieldByInternalName(strLName) as SPFieldLookup;
            ordersLName.LookupField = custLName.InternalName;
            ordersLName.StaticName = STATIC_CUST_LNAME;
            ordersLName.Update();

            // Create a secondary column: Phone.
            string strPhone = orders.Fields.AddDependentLookup("Phone", primary.Id);

            SPFieldLookup ordersPhone = orders.Fields.GetFieldByInternalName(strPhone) as SPFieldLookup;
            ordersPhone.LookupField = custPhone.InternalName;
            ordersPhone.StaticName = STATIC_CUST_PHONE;
            ordersPhone.Update();

            // Add columns to the default view.
            AddToDefaultView(orders, strFName);
            AddToDefaultView(orders, strLName);
            AddToDefaultView(orders, strPhone);
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            string logEntry = properties.Definition.DisplayName + " deactivation error: ";

            // Get an object representing either the current website (if the scope is Web)
            // or the root website (if the scope is Site).
            SPWeb web = properties.Feature.Parent as SPWeb;
            if (web == null)
            {
                SPSite site = properties.Feature.Parent as SPSite;
                if (site != null)
                    web = site.RootWeb;
            }
            if (web == null)
            {
                System.Diagnostics.Trace.WriteLine(logEntry + "Invalid scope");
                return;
            }

            // Get the Orders list.
            SPList orders = web.Lists.TryGetList("Contoso Orders");
            if (orders == null)
            {
                System.Diagnostics.Trace.WriteLine(logEntry + "List not found");
                return;
            }

            // Delete the lookup fields.
            // Note that you must delete dependent lookup fields
            // before deleting the primary lookup field.
            SPFieldLookup primaryLookup = orders.Fields.TryGetFieldByStaticName(STATIC_CUST_ID) as SPFieldLookup;
            if (primaryLookup != null && !primaryLookup.IsDependentLookup)
            {
                string[] dependentLookupNames = primaryLookup.GetDependentLookupInternalNames().ToArray();
                if (dependentLookupNames.Length != 0)
                {
                    foreach (string dependent in dependentLookupNames)
                    {
                        orders.Fields.Delete(dependent);
                    }
                }
                primaryLookup.Delete();
            }

        }

        public void AddToDefaultView(SPList list, string fieldName)
        {
            if (list != null && list.Fields.ContainsField(fieldName) && !list.DefaultView.ViewFields.Exists(fieldName))
            {
                SPView defaultView = list.DefaultView;
                defaultView.ViewFields.Add(fieldName);
                defaultView.Update();
            }
        }
    }
}

send mail to SPGROUP when bulk items added to list


public static void SendEmailsToGroup(string siteUrl, string groupTitle, string emailSubject, string emailBody)
{
    using (var site = new SPSite(siteUrl))
    {
        using (var web = site.OpenWeb())
        {
            var group = web.SiteGroups[groupTitle];
            foreach (var user in group.Users.Cast<SPUser>().Where(usr => !string.IsNullOrEmpty(usr.Email)))
                SPUtility.SendEmail(web, false, false, user.Email, emailSubject, emailBody);
        }
    }
}