2012-03-07 17 views
5

मैं वर्तमान में ईएफ 4.3 और कोड फर्स्ट का उपयोग कर रहा हूं। मेरी ऑब्जेक्ट्स का निर्माण (मेरे विचारों के माध्यम से - केवल ऑटो-जनरेटेड बनाएं का उपयोग करके) करता है, लेकिन जब मैं किसी ऑब्जेक्ट को संपादित करने का प्रयास करता हूं, तो यह किसी भी बदलाव को सहेजता नहीं है, जो कि, मेरे नेविगेशन गुणों को वापस जोड़ता है। मैं reading on relationships रहा हूं, लेकिन मुझे नहीं पता कि मेरे संदर्भ को कैसे बताना है कि संबंध बदल गया है।इकाई ढांचे में नेविगेशन गुणों के लिए अद्यतन करने के लिए रिश्ते नहीं मिल सकते

यहां मेरे कार्यान्वयन का कुछ उदाहरण कोड है।

[HttpPost] 
    public ActionResult Edit(ProjectViewModel projectViewModel) 
    { 
     if (ModelState.IsValid) 
     { 
      Project project = new Project(); 
      project.ProjectID = projectViewModel.ProjectID; 
      project.Name = projectViewModel.Name; 
      project.ProjectManager = repository.GetUser(projectViewModel.ManagerID); 
      repository.InsertOrUpdateProject(project); 
      repository.Save(); 
      return RedirectToAction("Index"); 
     } 
     ViewBag.Manager = new SelectList(repository.GetUsers(), "UserID", "FullName", projectViewModel.ManagerID); 
     return View(projectViewModel); 
    } 

मेरी परियोजना वस्तु के भीतर::

public class Project 
{ 
    public int ProjectID { get; set; } 
    [Required] 
    public string Name { get; set; } 

    // Navigation Properties 
    public virtual User Manager { get; set; } 
} 

यहाँ रिपोजिटरी से इसी विधि है (जहाँ मेरे संदर्भ

@* Snippet from my view where I link into my ViewModel. *@ 
<div class="row"> 
    <div class="editor-label"> 
     @Html.LabelFor(model => model.ManagerID) 
    </div> 
    <div class="editor-field"> 
     @Html.DropDownListFor(model => model.ManagerID, ViewBag.Manager as SelectList, String.Empty) 
     @Html.ValidationMessageFor(model => model.ManagerID) 
    </div> 
</div> 

यहाँ मेरी नियंत्रक कार्यान्वयन (मेरी संपादित की पोस्ट) है रहता है):

public void InsertOrUpdateProject(Project project) 
    { 
     if (program.ProjectID == default(int)) 
     { 
      context.Projects.Add(project); 
     } 
     else 
     { 
      context.Entry(project).State = EntityState.Modified; 
     } 
    } 

बस स्पष्ट होने के लिए, यह मेरी गुणों को अपडेट करने के लिए काम करता है, लेकिन यह मेरे नेविगेशन गुणों को अपडेट नहीं करता है (इस मामले में, प्रबंधक)। किसी भी मदद की सराहना करते हैं।

उत्तर

11

राज्य को Modified पर सेट करना केवल संशोधित के रूप में स्केलर गुणों को चिह्नित करता है, नेविगेशन गुण नहीं।

  • एक हैक (आप इसे पसंद नहीं करेगा)

    //... 
    else 
    { 
        var manager = project.Manager; 
        project.Manager = null; 
        context.Entry(project).State = EntityState.Modified; 
        // the line before did attach the object to the context 
        // with project.Manager == null 
        project.Manager = manager; 
        // this "fakes" a change of the relationship, EF will detect this 
        // and update the relatonship 
    } 
    
  • पुनः लोड (उत्सुक लोड हो रहा है) सहित डेटाबेस से परियोजना वर्तमान प्रबंधक: आप कई विकल्प हैं। फिर गुण सेट करें। ट्रैकिंग बदलें फिर से प्रबंधक के परिवर्तन का पता लगाएगा और एक अद्यतन लिखेंगे।

  • अपने मॉडल में Manager नेविगेशन संपत्ति के लिए एक विदेशी कुंजी संपत्ति का पर्दाफाश:

    public class Project 
    { 
        public int ProjectID { get; set; } 
        [Required] 
        public string Name { get; set; } 
    
        public int ManagerID { get; set; } 
        public virtual User Manager { get; set; } 
    } 
    

    अब ManagerID एक अदिश संपत्ति और Modified करने के लिए राज्य प्रॉपर्टी सेटिंग को शामिल नहीं है।

    Project project = new Project(); 
    project.ProjectID = projectViewModel.ProjectID; 
    project.Name = projectViewModel.Name; 
    project.ManagerID = projectViewModel.ManagerID; 
    repository.InsertOrUpdateProject(project); 
    repository.Save(); 
    
+0

उत्कृष्ट के लिए अद्यतन देखें। धन्यवाद। मैंने मूल रूप से विदेशी कुंजी मार्ग किया था, लेकिन इसके साथ कुछ समस्याएं थीं। बाहर निकलता है, यह काम करता है, लेकिन मुझे सब कुछ ठीक से मैप करने के लिए नेविगेशन प्रॉपर्टी के साथ [विदेशीकी ("नाम") विशेषता परिभाषित करना पड़ा। अपना उत्तर स्वीकार कर रहा है। धन्यवाद! – glockman

+0

@ user1240560: मेरे उत्तर में नामों के साथ यह वास्तव में विदेशीकी विशेषता (नाम सम्मेलन द्वारा एफके पहचान) के बिना काम करना चाहिए। लेकिन अगर आपके नाम थोड़ा अलग हैं और सम्मेलन के नियमों का पालन नहीं करते हैं, तो हाँ, आपको एनोटेशन की आवश्यकता है। – Slauma

+0

@ स्लुमा मैं तुमसे प्यार करता हूं, अन्य दृष्टिकोणों को कोड फर्स्ट मॉडल के साथ काम करना चाहिए, लेकिन डेटाबेस के साथ सबसे पहले जो मेरे लिए काम करता था वह आपका हैक था, मैं दिनों से इसके साथ गड़बड़ कर रहा था, और अब मुझे कहना है कि मुझे प्यार है आप भविष्य से बहुत –

-2

मुझे यकीन नहीं है कि नेविगेशन गुणों से आपका क्या मतलब है? क्या आपका मतलब विदेशी कुंजी संबंधों की तरह है? तो फिर निम्न डेटा एनोटेशन का प्रयास करें: अपने एफई प्रसंग

public class Project 
{ 
    public int ProjectID { get; set; } 

    [Required] 
    public string Name { get; set; } 

    [ForeignKey("YourNavigationProperty")] 
    public virtual UserManager { get; set; } 
} 

अद्यतन, और देखो क्या होता?

अद्यतन

public class Project 
{ 
    public int ProjectID { get; set; } 

    [Required] 
    public string Name { get; set; } 

    [ForeignKey("ManagerId")] 
    public ManagerModel UserManager { get; set; } 
} 

public class ManagerModel 
{ 
    [Key] 
    public int ManagerId { get; set; } 

    public String ManagerName { get; set; } 
} 

देखें कि अगर काम करता है?

+0

इसलिए मैं स्पष्ट रूप से अपने एफके नामों को परिभाषित नहीं करता हूं। मैं अपने प्रबंधक मान को एक नए प्रबंधक (जो काम पर प्रतीत होता है) पर सेट करने में सक्षम होना चाहता हूं लेकिन जब मैं SaveChanges() को कॉल करता हूं तो परिवर्तन वास्तव में डेटाबेस पर नहीं रह रहे हैं। मुझे यकीन नहीं है कि ऐसा कैसे किया जाए। – glockman

+0

मेरे उत्तर – jacqijvv

2

वहाँ कई विकल्प यहाँ हैं, मैं उनमें से 3 सूची जाएगा: इसके अलावा आप डेटाबेस से प्रबंधक उपयोगकर्ता लोड करने के लिए, तो आप सिर्फ आईडी आप अपने दृश्य से मिलता है प्रदान कर सकते हैं की जरूरत नहीं है:

विकल्प 1: GraphDiff

का उपयोग * यह अपने संदर्भ सही पर सेट की Configuration.AutoDetectChangesEnabled की जरूरत है।

बस NuGet

Install-Package RefactorThis.GraphDiff 

फिर

using (var context = new Context()) 
{ 
    var customer = new Customer() 
    { 
     Id = 12503, 
     Name = "Jhon Doe", 
     City = new City() { Id = 8, Name = "abc" } 
    }; 

    context.UpdateGraph(customer, map => map.AssociatedEntity(p => p.City)); 
    context.Configuration.AutoDetectChangesEnabled = true; 

    context.SaveChanges(); 
} 

साथ GraphDiff स्थापित के लिए GraphDiff बारे में अधिक जानकारी here देखो।

विकल्प 2: खोज और संपादन

संदर्भ के लिए यह ट्रैक करने के लिए एफई के साथ अपने इकाई सर्च कर रहे हैं। फिर गुणों को संपादित करें।

* इसे आपके संदर्भ सेट के Configuration.AutoDetectChangesEnabled की आवश्यकता है।

var customer = new Customer() 
{ 
    Id = 12503, 
    Name = "Jhon Doe", 
    City = new City() { Id = 8, Name = "abc" } 
}; 

using (var context = new Contexto()) 
{ 
    var customerFromDatabase = context.Customers 
             .Include(x => x.City) 
             .FirstOrDefault(x => x.Id == customer.Id); 

    var cityFromDataBase = context.Cities.FirstOrDefault(x => x.Id == customer.City.Id); 

    customerFromDatabase.Name = customer.Name; 
    customerFromDatabase.City = cityFromDataBase;     

    context.Configuration.AutoDetectChangesEnabled = true; 
    context.SaveChanges(); 
} 

विकल्प 3: एक अदिश संपत्ति

का उपयोग करते हुए प्रदर्शन इस के अन्दर ही सबसे अच्छा तरीका है, लेकिन डेटाबेस चिंताओं के साथ अपने वर्ग में यह गंदगी। क्योंकि आपको आईडी को मैप करने के लिए एक स्केलर (आदिम प्रकार) संपत्ति बनाने की आवश्यकता होगी।

* इस तरह Configuration.AutoDetectChangesEnabled को सत्य पर सेट करने की आवश्यकता नहीं है। और आपको इकाइयों को पुनः प्राप्त करने के लिए डेटाबेस को एक क्वेरी करने की आवश्यकता नहीं होगी (जैसा कि पहले दो विकल्प होंगे - हां ग्राफडिफ दृश्यों के पीछे करता है!)।

var customer = new Customer() 
{ 
    Id = 12503, 
    Name = "Jhon Doe", 
    City_Id = 8, 
    City = null 
}; 

using (var contexto = new Contexto()) 
{ 
    contexto.Entry(customer).State = EntityState.Modified; 
    contexto.SaveChanges(); 
} 
संबंधित मुद्दे

 संबंधित मुद्दे